QT开发学习笔记(网络下载实例 )
创始人
2025-05-31 17:17:34
0

网络下载实例

Qt 网 络 模 块 还 提 供 了 直 接 访 问 如 HTTP , FTP 等 网 络 协 议 的 类 , 这 些 类 是

QNetworkAccessManager、QNetworkRequest 和 QNetworkReply。

通常需要这三个类协作才能完成一个网络操作。可以用于从网络获取时间,天气和图片等
等数据。比如本例需要下载一张图片,大概流程如下。

由 QNetworkRequest 类设置一个 URL 地址发起网络协议请求,QNetworkRequest 类保存要
用 QNetworkAccessManager 发送的请求。QNetworkRequest 是网络访问 API 的一部分,是一个
持有通过网络发送请求所需信息的类。它包含一个 URL 和一些可用于修改请求的辅助信息。
QNetworkAccessManager 类允许应用程序发送网络请求并接收响应。在 QNetworkRequest

发起网络请求后,QNetworkAccessManager 负责发送网络请求,创建网络响应。
QNetworkReply类就用于 QNetworkAccessManager 创建的网络响应。最终由QNetworkReply

处理网络响应。它提供了 finished()、readyRead()和 downloadProgress()等信号,可以监测网络响
应的执行情况。并且 QNetworkReply 继承于 QIODevice,所以 QNetworkReply 支持流读写,可
以直接用 read()和 write 等功能。

11.4.1 应用实例

本例目的:了解 QNetworkAccessManager、QNetworkRequest 和 QNetworkReply 类的使用。

例 12_imagedownload,下载小图片(难度:一般)。项目路径为 Qt/2/12_imagedownload。
本例大体流程,设置一个下载图片的 URL,通过 networkReply 处理响应后,从流中读取图片的
数据,然后保存到本地。

项目文件 12_imagedownload.pro 文件第一行添加的代码部分如下。

12_imagedownload.pro 编程后的代码

1 QT += core gui network 2 3 greaterThan(QT_MAJOR_VERSION, 4): QT += widgets 4 5 CONFIG += c++11 6 7 # The following define makes your compiler emit warnings if you use 8 # any Qt feature that has been marked deprecated (the exact warnings 9 # depend on your compiler). Please consult the documentation of the 10 # deprecated API in order to know how to port your code away from it. 11 DEFINES += QT_DEPRECATED_WARNINGS 12 13 # You can also make your code fail to compile if it uses deprecated APIs. 14 # In order to do so, uncomment the following line. 15 # You can also select to disable deprecated APIs only up to a certain 
version of Qt. 16 #DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the 
APIs deprecated before Qt 6.0.0 17 18 SOURCES += \ 19 main.cpp \ 20 mainwindow.cpp 21 22 HEADERS += \ 23 mainwindow.h 24 25 # Default rules for deployment. 26 qnx: target.path = /tmp/$${TARGET}/bin 27 else: unix:!android: target.path = /opt/$${TARGET}/bin 28 !isEmpty(target.path): INSTALLS += target 

在头文件“mainwindow.h”具体代码如下。

mainwindow.h 编程后的代码

 /****************************************************************** Copyright © Deng Zhimao Co., Ltd. 1990-2021. All rights reserved. * @projectName 12_imagedownload * @brief mainwindow.h * @author Deng Zhimao * @email 1252699831@qq.com * @net www.openedv.com * @date 2021-04-16 *******************************************************************/ 1 #ifndef MAINWINDOW_H 2 #define MAINWINDOW_H 3 4 #include  5 #include  6 #include  7 #include  8 #include  9 #include  10 #include  11 #include  12 #include  13 #include  14 15 class MainWindow : public QMainWindow 16 { 17 Q_OBJECT 18 19 public: 20 MainWindow(QWidget *parent = nullptr); 21 ~MainWindow(); 22 private: 23 /* 网络管理 */ 24 QNetworkAccessManager *networkAccessManager; 25 26 /* 标签 */ 27 QLabel *label[3]; 28 29 /* 按钮 */ 30 QPushButton *pushButton; 31 32 /* 下载进度条 */ 33 QProgressBar *progressBar; 34 35 /* 水平布局 */ 36 QHBoxLayout *hBoxLayout[2]; 37 38 /* 垂直布局 */ 39 QVBoxLayout *vBoxLayout; 40 41 /* 水平容器 */ 42 QWidget *hWidget[2]; 43 44 /* 垂直容器 */ 45 QWidget *vWidget; 46 47 /* 链接输入框 */ 48 QLineEdit *lineEdit; 49 50 private slots: 51 /* 读取数据 */ 52 void readyReadData(); 53 54 /* 响应完成处理 */ 55 void replyFinished(); 56 57 /* 下载进度管理 */ 58 void imageDownloadProgress(qint64, qint64); 59 60 /* 点击开始下载 */ 61 void startDownload(); 62 63 /* 响应错误处理函数 */ 64 void networkReplyError(QNetworkReply::NetworkError); 65 }; 66 #endif // MAINWINDOW_H 

头文件里主要是声明界面用的元素,及一些槽函数。重点是声明 networkAccessManager。

在源文件“mainwindow.cpp”具体代码如下。

mainwindow.cpp 编程后的代码

 /****************************************************************** Copyright © Deng Zhimao Co., Ltd. 1990-2021. All rights reserved. * @projectName 12_imagedownload * * @brief mainwindow.cpp * @author Deng Zhimao * @email 1252699831@qq.com * @net www.openedv.com * @date 2021-04-16 *******************************************************************/ 1 #include "mainwindow.h" 2 #include  3 #include  4 5 MainWindow::MainWindow(QWidget *parent) 6 : QMainWindow(parent) 7 { 8 /* 设置主窗体的位置与大小 */ 9 this->setGeometry(0, 0, 800, 480); 10 11 /* 标签 0, 显示下载的图像 */ 12 label[0] = new QLabel(); 13 /* 标签 1, 显示 URL 标签 */ 14 label[1] = new QLabel(); 15 /* 下载进度标签 */ 16 label[2] = new QLabel(); 17 18 /* 下载图片链接输入框 */ 19 lineEdit = new QLineEdit(); 20 21 /* 下载按钮 */ 22 pushButton = new QPushButton(); 23 24 /* 下载进度条 */ 25 progressBar = new QProgressBar(); 26 27 /* 水平布局 */ 28 hBoxLayout[0] = new QHBoxLayout(); 29 hBoxLayout[1] = new QHBoxLayout(); 30 31 /* 垂直布局 */ 32 vBoxLayout = new QVBoxLayout(); 33 34 /* 水平容器 */ 35 hWidget[0] = new QWidget(); 36 hWidget[1] = new QWidget(); 37 
38 /* 垂直容器 */ 39 vWidget = new QWidget(); 40 41 label[1]->setText("URL 链接:"); 42 label[2]->setText("文件下载进度:"); 43 44 pushButton->setText("下载"); 45 46 /* 设置下载链接地址 */ 47 lineEdit->setText("https://ss0.bdstatic.com/70cFuH" 48 "Sh_Q1YnxGkpoWK1HF6hhy/it/u=42710" 49 "87328,1384669424&fm=11&gp=0.jpg"); 50 /* 设置标签的最小显示大小 */ 51 label[0]->setMinimumSize(this->width(), 52 this->height() * 0.75); 53 54 /* 根据文本文字大小自适应大小 */ 55 label[1]->setSizePolicy(QSizePolicy::Fixed, 56 QSizePolicy::Fixed); 57 label[2]->setSizePolicy(QSizePolicy::Fixed, 58 QSizePolicy::Fixed); 59 pushButton->setSizePolicy(QSizePolicy::Fixed, 60 QSizePolicy::Fixed); 61 62 /* 水平布局 0 添加元素 */ 63 hBoxLayout[0]->addWidget(label[1]); 64 hBoxLayout[0]->addWidget(lineEdit); 65 hBoxLayout[0]->addWidget(pushButton); 66 67 /* 设置水平布局 0 为水平容器的布局 0 */ 68 hWidget[0]->setLayout(hBoxLayout[0]); 69 70 /* 水平布局 1 添加元素 */ 71 hBoxLayout[1]->addWidget(label[2]); 72 hBoxLayout[1]->addWidget(progressBar); 73 74 /* 设置水平布局 1 为水平容器的布局 1 */ 75 hWidget[1]->setLayout(hBoxLayout[1]); 76 77 /* 垂直布局添加元素 */ 78 vBoxLayout->addWidget(label[0]); 79 vBoxLayout->addWidget(hWidget[0]); 80 vBoxLayout->addWidget(hWidget[1]); 81 82 /* 设置垂直布局为垂直容器的布局 */ 83 vWidget->setLayout(vBoxLayout); 84 85 /* 设置居中 */ 86 setCentralWidget(vWidget); 87 88 /* 网络管理 */ 89 networkAccessManager = new QNetworkAccessManager(this); 90 91 /* 信号槽连接 */ 92 connect(pushButton, SIGNAL(clicked()), 93 this, SLOT(startDownload())); 94 95 } 96 97 MainWindow::~MainWindow() 98 { 99 } 100 101 void MainWindow::startDownload() 102 { 103 /* 获取 URL 链接 */ 104 QUrl newUrl(QUrl(lineEdit->text())); 105 106 /* 如果下载链接无效,则直接返回 */ 107 if (!newUrl.isValid()) { 108 QMessageBox::information(this, "error", "invalid url"); 109 return; 110 } 111 112 /* 网络请求 */ 113 QNetworkRequest networkRequest; 114 115 /* 设置下载的地址 */ 116 networkRequest.setUrl(newUrl); 117 118 /* 网络响应 */ 119 QNetworkReply *newReply = 120 networkAccessManager->get(networkRequest); 121 122 /* 信号槽连接 */ 123 connect(newReply, SIGNAL(finished()), 124 this, SLOT(replyFinished())); 125 connect(newReply, SIGNAL(readyRead()), 126 this, SLOT(readyReadData())); 127 connect(newReply, SIGNAL(downloadProgress(qint64, qint64)), 128 this, SLOT(imageDownloadProgress(qint64, qint64))); 129 connect(newReply, 130 SIGNAL(error(QNetworkReply::NetworkError)), 131 this, 132 SLOT(networkReplyError(QNetworkReply::NetworkError ))); 133 } 134 135 void MainWindow::readyReadData() 136 { 137 /* 设置按钮不可用,防止未完成,再次点击 */ 138 pushButton->setEnabled(false); 139 140 /* 获取信号发送者 */ 141 QNetworkReply *reply = (QNetworkReply *)sender(); 142 143 QFile imageFile; 144 /* 保存到当前路径,名称为"下载的.jpg" */ 145 imageFile.setFileName(QCoreApplication::applicationDirPath() 146 + "/下载的.jpg"); 147 148 /* 如果此图片已经存在,则删除 */ 149 if (imageFile.exists()) 150 imageFile.remove(); 151 152 /* 读取数据 */ 153 QByteArray data = reply->readAll(); 154 /* 如果数据为空,返回 */ 155 if (data.isEmpty()) { 156 qDebug()<<"data is null, please try it again!"< 165 qDebug()<<"not JPG data, please try it again!"< 177 /* 获取信号发送者 */ 178 QNetworkReply *reply = (QNetworkReply *)sender(); 179 180 /* 防止内存泄漏 */ 181 reply->deleteLater(); 182 183 /* 判断当前执行程序下的图像是否下载完成 */ 184 QFile imageFile(QCoreApplication::applicationDirPath() 185 + "/下载的.jpg"); 186 if (imageFile.exists()) { 187 /* 显示下载的图像 */ 188 label[0]->setPixmap(QPixmap(imageFile.fileName())); 189 qDebug() <<"已经成功下载,文件路径为:" 190 <clear(); 194 195 /* 设置按钮可用 */ 196 pushButton->setEnabled(true); 197 } 198 199 void MainWindow::imageDownloadProgress(qint64 bytes, 200 qint64 totalBytes) 201 { 202 /* 设置进度条的最大值 */ 203 progressBar->setMaximum(totalBytes); 204 /* 设置当前值 */ 205 progressBar->setValue(bytes); 206 } 207 
208 /* 网络响应处理函数 */ 209 void MainWindow::networkReplyError(QNetworkReply::NetworkError 210 error) 211 { 212 switch (error) { 213 case QNetworkReply::ConnectionRefusedError: 214 qDebug()<<"远程服务器拒绝连接"<

第 89 行,全局变量 networkAccessManager 实例化。
第 101 行~133 行,首先从单行输入框里获取 URL 链接为 newUrl,判断链接的有效性。然
后创建局部变量 networkRequest,设置 networkRequest 请求 URL 为 newUrl。QNetworkReply
*newReply = networkAccessManager->get(networkRequest);为最重要的代码,所有响应本次的操
作都交给了 newReply。通过信号槽处理对应的操作。
第 135~173 行,这部分代码就是从 newReply 流里读取网络下载的数据。
第 160~167 行,这里笔者做了一些处理,从网络下载的数据可能遇到数据丢失或者下载错
误的情况。本例是从百度里下载一张 JPG 格式的图片,因为 JPG 图片的判断依据是第一个字节
和第二个字节的数据是 0xff 和 0xd8,倒数第一个和倒数第二个字节数据分别是 0xd9 和 0xff。
如果都对,那么判断此数据为 JPG 图片数据。然后进行保存,否则则不保存图片。处理数据往
往是需要的,我们经常要对下载的数据进行处理。
第 174~197 行,网络响应完成。记得要删除 reply,防止内存泄漏。如果下载成功图片,则
显示图片到 label[0]上。
第 209~225 行,网络响应错误处理函数。

11.4.2 程序运行效果

点击下载按钮后,可以看到本次下载的图片已经保存到当前编译输出的路径下,名字叫“下
载的.jpg”,并显示到界面上。由于文件下载的速度非常快,所以下载的进度条一下子就变成了

100%。若想看见下载进度条下载进度缓慢一些,可以修改本例去下载其他文件,注意不要保存
为 jpg 图片了。注意:此程序里的下载链接可能失效,请替换自己的图片链接。
在这里插入图片描述

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
美团联名卡审核成功待激活(美团... 今天百科达人给各位分享美团联名卡审核成功待激活的知识,其中也会对美团联名卡审核未通过进行解释,如果能...
一帆风顺二龙腾飞三阳开泰祝福语... 本篇文章极速百科给大家谈谈一帆风顺二龙腾飞三阳开泰祝福语,以及一帆风顺二龙腾飞三阳开泰祝福语结婚对应...