在Qt中,提供了QNetworkAccessManager这个类,用于完成基于Http协议的数据上传和下载,该类既可以发送网络请求,也可以接受网络回复。而具体的网络请求是通过QNetworkRequest类发送的,具体的网络回复是通过QNetworkReply类来接收的。
本文将利用上面提到的几个类实现使用Http协议,获取指定的页面,并说明如何向该页面传递POST参数,最后在此基础上添加一个进度条,用于检测页面文件读取进度。
基本原理
由于QNetworkAccessManager类中包含了一组标准的数据请求函数,因此可以通过该类的对象发送数据请求函数;每个请求函数执行完毕时都回返回一个QNetworkReply对象。当所有请求的数据都到达本地后,将引发一个finished()信号,该信号关联了一个处理返回数据的槽函数。具体的实现可参考下述代码:
由于上面的这些类属于网络模块,所以需要在工程文件.pro中添加下面的语句,表明我们使用了网络模块:
QT += network
另外,还需要在有文件中添加包含头文件:
可以看到,上述的基本原理大部分都在构造函数中完成。首先创建了一个QNetworkAccessManager对象manager;接着将manager所引发的finished()信号与replyFinished()槽进行关联;最后通过get()发送数据请求。
get()用于发送请求并获得目标地址中的数据,具体的数据请求则是通过创建一个QNetworkRequest类的对象而完成的。只要数据请求发送成功,则开始下载数据。当所有的数据下载完成后,就返回一个QNetworkReply类型的对象。同时manager对象将发送一个finished()信号,引发replyFinished槽函数的执行。
当执行上述的槽函数时,就说明目标地址的数据已经下载完毕。此时槽函数要做的就是将这些数据显示出来。这里我们只对文本数据进行转换。对这些数据的转换动作可参考下述的代码:
为了能够正确显示中文,我们创建QTextCodec对象。利用readAll函数可以读取数据请求返回的所有数据,并且利用toUnicode函数将这些数据转换成QString类型。最后在用户界面中的TextBrower控件中显示出来。
按照上面的方法就可以下载指定地址的数据。如下图:
Qt使用Http协议获取指定页面内容
当返回的数据显示完毕后,利用deleteLater函数将返回的数据删除。
发送Post请求
上面的获取指定页面的方式是采用get的方式获取的,如果想通过post的方式传递参数,需要自己构造HTTP请求头部,在上面的代码中,将原有的构造函数代码修改成下面的代码即可。
在上面的程序中,以post的方式请求指定页面,如果获取成功了,则会调用replyFinished这个槽函数,该函数的处理过程还是和原先的一样。
监控下载文件进度
现在,我们使用上面提到的这些类下载网上文件,一般我们下载文件都想要看到下载进度,所以现在,我们需要给请求文件的过程添加进度条,显示当前下载的进度。
界面布局
现在在界面上,需要放置一个ProcessBar控件,用于显示获取页面或文件下载的进度,还要有一个LineEdit控件,用于获取页面URL,页面布局如下:
Qt下载页面文件:页面布局
类的头文件
widget.h头文件中代码:
构造函数
然后在构造函数中初始化manager变量,以及隐藏进度条。
单击下载按钮处理函数
当点击按钮时,开始加载指定的页面,单击按钮信号的处理槽函数如下:
这里先从界面中获取输入的地址,然后分解出文件名。因为地址中可能没有文件名(比如输入),这时我们就使用一个默认的文件名。然后我们用这个文件名新建一个文件,然后我们以写入方式打开文件。最后进行链接,并显示进度条。
链接请求函数
链接请求函数startRequest代码如下:
上面程序中的manager->get(QNetworkRequest(url))语句返回的是一个QNetworkReply对象,这里我们获得这个对象,使用它完成显示数据下载进度的功能。这里主要是关联了几个信号和槽。当有可用数据时,reply就会发出readyRead()信号,我们这时就可以将可用的数据保存下来。就是在这里,实现了数据分段下载保存,这样下载完所有数据再保存,要节省很多内存。而利用reply的downloadProgress()信号,很容易就实现了进度条的显示。
保存文件
当有可用数据时,reply就会发出readyRead()信号,我们这时就可以将可用的数据保存下来,相应的槽函数如下:
这里当file可用时,将下载的数据写入文件。
更新进度条函数
每当有数据到来时,都更新进度条。
完成下载
这里只是当下载完成后,进行一些处理。
最后的程序运行结果如下所示:
Qt使用HTTP下载文件
本文参考:《》