Qt:60---网络编程之HTTP通信(QNetworkRequest、QNetworkReply、NetworkAccessManager)
原创
©著作权归作者所有:来自51CTO博客作者董哥的黑板报的原创作品,请联系作者获取转载授权,否则将追究法律责任
一、高层网络协议类简介
- Qt网络模块提供了一些类实现OSI 7层网络模型中高层的网络协议,如HTTP、FTP、SNMP等
-
这些类主要为:
-
QNetworkRequest类:通过一个URL地址发起网络协议请求,也保存网络请求的信息,目前支持HTTP、FTP和局部文件URLs的下载或上传
-
NetworkAccessManager类:用于协调网络操作。在QNetworkRequest发起一个网络请求后,NetworkAccessManager负责发送网络请求,创建网络响应
-
QNetworkReply类:表示网络请求的相应。由NetworkAccessManager在发送一个网络请求后创建一个网络响应。QNetworkReply提供finished()、readyRead()、downloadProgress()可以监测网络响应的执行情况,执行相应的操作
-
QNetworkReply是QIODevice的子类,所以QNetworkReply支持流读写功能,也支持异步或同步工作
- 想要使用那个类就添加相应的头文件,头文件名与类型相同
二、演示案例
第一步
- 创建一个基于QMainWindow的项目,类名采取默认值。并设计界面
- 在URL中输入一个网络文件URL,设置下载文件保存路径后,点击下载按钮开始下载文件到目录中。进度条(Progress Bar)表示文件下载进度
第二步
//只列出了自己手写的代码,系统的默认代码省略了
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QFile>
#include <QDir>
#include <QMessageBox>
#include <QUrl>
#include <QFileInfo>
class MainWindow : public QMainWindow
{
private:
QNetworkAccessManager networkManager; //网络管理
QNetworkReply *reply; //网络响应
QFile *downloadedFile; //下载保存的临时文件
private slots:
//自定义槽函数
void on_finished();
void on_readyRead();
void on_downloadProgress(qint64 bytesRead,qint64 totalBytes);
};
第三步
//在当前应用程序目录下创建一个名为temp的临时目录
void MainWindow::on_btnDefaultPath_clicked()
{
//获取当前应用程序的路径
QString curPath=QDir::currentPath();
//在当前目录下创建一个临时目录temp
QDir dir(curPath);//打开当前应用程序的路径
QString sub="temp";
dir.mkdir(sub);
ui->editPath->setText(curPath+"/"+sub+"/");
}
第四步
void MainWindow::on_btnDefaultPath_clicked()
{
//获取当前应用程序的路径
QString curPath=QDir::currentPath();
//在当前目录下创建一个临时目录temp
QDir dir(curPath);//打开当前应用程序的路径
QString sub="temp";
dir.mkdir(sub);
ui->editPath->setText(curPath+"/"+sub+"/");
}
void MainWindow::on_btnDownload_clicked()
{
//判断是否输入了URL
QString urlSpec=ui->editURL->text().trimmed();
if(urlSpec.isEmpty())
{
QMessageBox::information(this,QStringLiteral("错误"),QStringLiteral("请指定需要下载的文件URL"));
return;
}
//将路径转为一个URL变量,判断输入的URL是否有误
QUrl newUrl=QUrl::fromUserInput(urlSpec);
if(!newUrl.isValid())
{
QMessageBox::information(this,QStringLiteral("错误"),QString(QStringLiteral("无效URL:%1\n错误信息:%2")).arg(urlSpec,newUrl.errorString()));
return;
}
//判断是否打开了一个目录来保存下载的文件
QString tempDir=ui->editPath->text().trimmed();
if(tempDir.isEmpty())
{
QMessageBox::information(this,QStringLiteral("错误"),QStringLiteral("请指定下载文件保存目录"));
return;
}
//如果想要下载的文件已经存在了,则先移除原先存在的文件
QString fullFileName=tempDir+newUrl.fileName();
if(QFile::exists(fullFileName))
QFile::remove(fullFileName);
//尝试打开要下载的文件
downloadedFile=new QFile(fullFileName);
if(!downloadedFile->open(QIODevice::WriteOnly))
{
QMessageBox::information(this,QStringLiteral("错误"),QStringLiteral("临时文件打开错误"));
return;
}
ui->btnDownload->setEnabled(false);
//用QNetworkAccessManager发布网络请求,请求下载URL地址表示的文件并创建网络响应
reply=networkManager.get(QNetworkRequest(newUrl));
//关联信号与槽
connect(reply,SIGNAL(finished()),this,SLOT(on_finished()));
connect(reply,SIGNAL(readyRead()),this,SLOT(on_readyRead()));
connect(reply,SIGNAL(downloadProgress(qint64,qint64)),
this,SLOT(on_downloadProgress(qint64,qint64)));
}
第五步
void MainWindow::on_readyRead()
{
//读取下载的数据
downloadedFile->write(reply->readAll());
}
void MainWindow::on_downloadProgress(qint64 bytesRead,qint64 totalBytes)
{
//设置进度条的值
ui->progressBar->setMaximum(totalBytes);
ui->progressBar->setValue(bytesRead);
}
//网络请求结束之后
void MainWindow::on_finished()
{
QFileInfo fileInfo;
fileInfo.setFile(downloadedFile->fileName());
//关闭打开的网络文件,然后置空
downloadedFile->close();
delete downloadedFile;
downloadedFile=Q_NULLPTR;
//删除网络响应并置空
reply->deleteLater();
reply=Q_NULLPTR;
QMessageBox::information(this,QStringLiteral("提示"),QStringLiteral("下载成功"));
//如果设置了下载完成后打开,就打开文件
if(ui->checkOpen->isChecked())
{
//调用缺省的应用程序软件打开下载的文件
QDesktopServices::openUrl(QUrl::fromLocalFile(fileInfo.absoluteFilePath()));
ui->btnDownload->setEnabled(true);
}
}
演示效果