Qt学习day08 Http客户端(代码下载器)

本文详细介绍了一个HTTP客户端代码下载器的设计与实现过程,包括需求分析、概要设计、详细设计、代码编写、运行测试、代码重构及产品发布等阶段。深入探讨了多窗口编程技巧,如何使用QT库进行网络通信,解析HTTP协议,并实现文件下载功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

多窗口编程:
1)程序启动时,先显示子窗口,再显示主界面//windows1
2)程序启动时,先显示主界面,再弹出子窗口//windows2
3)程序启动时,显示出多个窗口//windows3


项目:Http客户端(代码下载器)
1)需求分析
–》显示下载代码界面
–》处理"子目录"链接
–》实现对文件下载
2)概要设计
3)详细设计
4)编写代码
5)运行测试
*6)代码重构
7)产品发布
8)升级维护

Http协议简介:
1)请求:客户端向服务器发送消息
2)响应:服务器给客户端返回消息

QT中相关类:
1)QNetworkAccessManger//管理通信中请求和响应
2)QNetworkRequest//请求
3)QNetworkReply//响应
4)QUrl//网址
5)QFile/QFileInfo //文件操作
6)QDir//目录
7)QTextBrowser//图形控件:文本浏览器

工程名字:HttpClient
类名:MainWindow(默认)

忽略下面提示:
qt.network.ssl: QSslSocket: cannot resolve SSLv2_client_method
qt.network.ssl: QSslSocket: cannot resolve SSLv2_server_method

任务:
1)增加登录对话框
2)将下载文件操作,放到子线程中,实现多文件的同时下载
3)下载文件时,指定保存"/home/tarena/Downloads/"目录下面

参考代码如下:
HttP代码下载器:

头文件代码:
public:
    QNetworkAccessManager* manager;//管理通信//************************************************
private:
    QNetworkRequest request;//请求//************************************************
    QNetworkReply* reply;//响应//************************************************
    QUrl currentUrl;//记录当前的Url地址//************************************************
    QByteArray buf;//保存接收的响应数据//************************************************
    //容器,保存要支持下载的文件类型
    QList<QString> fileType;//************************************************

private:
    //向服务器发送请求
    void sendRequest();//************************************************1

private slots:
    //处理登录认证的槽函数
    void onAuthenticationRequired(QNetworkReply*,QAuthenticator*);//************************************************2
    //接收响应数据的槽函数
    void onReadyRead();//************************************************3
    //接收响应数据完成时执行的槽函数
    void onFinished();//************************************************4
    //处理目录链接的槽函数
    void onAnchorClicked(const QUrl& url);//************************************************5

private:
    //下载文件
    void downloadFile(const QUrl& fileUrl);//************************************************6

源文件代码:

①《构造函数》MainWindow(QWidget *parent) :QMainWindow(parent),ui(new Ui::MainWindow)
    manager = new QNetworkAccessManager(this);//************************************************1
    request.setUrl(QUrl("http://code.tarena.com.cn/"));//************************************************2
    //向服务器发送请求
    sendRequest();//************************************************3

    //点击界面的链接时,发送信号anchorClicked,
    //参数表示点击链接的URL地址
    connect(ui->textBrowser,SIGNAL(anchorClicked(QUrl)),
	    this,SLOT(onAnchorClicked(QUrl)));//************************************************4

② 《向服务器发送请求》sendRequest()
    //向服务器发送请求
    reply = manager->get(request);//************************************************
    //如果服务器需要进行登录认证,manager会发送认证
    //信号:authenticationRequired
    connect(manager,SIGNAL(
        authenticationRequired(
            QNetworkReply*,QAuthenticator*)),
        this,SLOT(onAuthenticationRequired(
            QNetworkReply*,QAuthenticator*)));//************************************************
    //如果认证成功,响应数据到来,发送信号readyRead
    connect(reply,SIGNAL(readyRead()),
        this,SLOT(onReadyRead()));//************************************************
    //响应数据接收结束,发送信号finished
    connect(reply,SIGNAL(finished()),
        this,SLOT(onFinished()));//************************************************


③ 《处理登录认证的槽函数》onAuthenticationRequired(QNetworkReply*,QAuthenticator* authenticator)
    //从登录认证子窗口中,获取用户名和密码在进行认证
    LoginDialog login(this);//************************************************
    //显示登录窗口,并进入事件循环,点击上面Ok/Cancel
    //时都会退出登录窗口,但是返回值不同.
    //如果点击Ok按钮退出,返回QDialog::Accepted
    if(login.exec() == QDialog::Accepted){
        authenticator->setUser(login.getUsername());//************************************************
        authenticator->setPassword(login.getPassword());//************************************************
    }

④ 《接收响应数据的槽函数》onReadyRead()
    //读取响应数据,并保存
    buf += reply->readAll();//************************************************
    //保存当前URl地址
    currentUrl = reply->url();//************************************************

⑤ 《接收响应数据完成时执行的槽函数》onFinished()
    //显示响应数据
    ui->textBrowser->setText(buf);//************************************************

⑥ 《处理目录链接的槽函数》onAnchorClicked(const QUrl &url)
    QUrl newUrl;
    //如果点击是不是"../",新的URL=当前URL+点击URL
    if(url.toString() != "../"){
        newUrl = currentUrl.toString() + url.toString();//************************************************
    }
    //如果点击是"../"
    else{
        //如果当前在首页,什么也不做
        if(currentUrl.toString() =="http://code.tarena.com.cn/")//************************************************
        {
            return;//************************************************
        }
        //如果不在首页,去掉最后一级链接路径
        //查找目录路径中倒数第二次出现"/"位置
        int pos = currentUrl.toString(
                    ).lastIndexOf("/",-2);//************************************************
        //字符串截断,去掉后面的路径
        newUrl =
            currentUrl.toString().mid(0,pos+1);//************************************************
    }
    //设置新的请求URL
    request.setUrl(newUrl);//************************************************
    //发送新的请求
    sendRequest();//************************************************
    //判断点击URL如果不是目录则执行文件下载操作.
    if(url.toString().lastIndexOf("/")==-1){//************************************************
        downloadFile(newUrl);//************************************************
        return;
    } 

⑦  《下载文件》downloadFile(const QUrl& fileUrl)
    //创建下载文件线程
    QThread *thread = new QThread;//************************************************
    //创建下载文件对象
    Download* download = new Download(fileUrl);//************************************************
    //将下载文件对象移动到子线程中
    download->moveToThread(thread);//************************************************

    //设置下载文件请求的URL
    download->request.setUrl(fileUrl);//************************************************1(初始化)

    //发送获取下载文件的请求
    download->reply = manager->get(download->request);//************************************************2(初始化)
    
    //响应数据到来,在子线程中完成下载操作
    //download已经移动到子线程中,通过信号出发里面槽将在子线程中运行
    connect(download->reply,SIGNAL(readyRead()),
            download,SLOT(ReceiveFile()));//************************************************3 
    connect(download->reply,SIGNAL(downloadProgress(qint64,qint64)),
            download,SLOT(onDownloadProgress(qint64,qint64)));//************************************************3
    connect(download->reply,SIGNAL(finished()),
            download,SLOT(ReceiveFileFinished()));//************************************************4
    //开启子线程
    thread->start();//************************************************

注:
Download类实现如下:
头文件:
private:
    QNetworkRequest request;//请求//************************************************
    QNetworkReply* reply;//响应//************************************************
    QUrl fileUrl;//下载文件的URL地址//************************************************
    QFile* file;//************************************************
    //将MainWindow类声明为当前类的友元,友元类可以访问当前类的任何成员
    friend class MainWindow;//************************************************

private slots:
    //接收文件的槽函数
    void ReceiveFile();//************************************************
    //更新显示文件下载进度的槽函数
    //参数:已收到数据的字节数/总字节数
    void onDownloadProgress(qint64,qint64);//************************************************
    //接收文件完成的槽函数
    void ReceiveFileFinished();//************************************************

源文件:
① 《构造函数》Download(const QUrl& url):fileUrl(url)
    //根据URL获取文件名
    QFileInfo fileInfo = fileUrl.path();//************************************************
    QString filename = fileInfo.fileName();//************************************************
    //指定下载文件放到主目录的Download下面
    QString path = QDir::homePath() + "/Downloads/"+ filename;//************************************************
    //在本地创建同名的文件
    file = new QFile(path);//************************************************
    //以写的方式打开文件
    file->open(QIODevice::WriteOnly);//************************************************

② 《接收文件的槽函数》ReceiveFile()
    file->write(reply->readAll());//************************************************

③ 《已收到数据的字节数/总字节数》onDownloadProgress(qint64 readBytes,qint64 totalBytes)
    qint64 progress=readBytes*100/totalBytes;//百分比//************************************************
    qDebug() << file->fileName() << ":" << progress << "%....";//************************************************

④ 《接收文件完成的槽函数》ReceiveFileFinished()
    qDebug() << file->fileName() << "文件下载完成";//************************************************
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值