QT网络(四):HTTP通信

Qt 网络模块提供一些类来实现 OSI 七层网络模型中高层的网络协议,如 HTTP、FTP、SNMP 等,这些类主要是 QNetworkRequest、QNetworkAccessManager 和 QNetworkReply。QNetworkRequest 类

通过 URL 发起网络协议请求,其也保存网络请求的信息,目前支持 HTTP、 FTP 和本地文件 URL 的下载或上传。

QNetworkAccessManager 类

用于协调网络操作,在 QNetworkRequest 发起网络请求后, QNetworkAccessManager 负责发送网络请求,以及创建网络响应。

QNetworkReply 类

表示网络请求的响应,由 QNetworkAccessManager 在发送网络请求后创建网 络响应。QNetworkReply 提供的信号 finished()、readyRead()、downloadProgress()可用于监测网络响应的执行情况,从而进行相应的操作。

QNetworkReply 继承了QIODevice,因此也支持流数据读写功能。

HTTP网络文件下载示例

URL 里的 HTTP 地址可以表示 为任何类型的文件,如 html 文件、pdf 文件、doc 文件、exe 文件等。

主窗口头文件如下:

cpp 复制代码
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include    <QMainWindow>
#include    <QNetworkAccessManager>
#include    <QNetworkReply>
#include    <QFile>
#include    <QUrl>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT
private:
    QNetworkAccessManager networkManager;   //网络管理
    QNetworkReply *reply;   //网络响应
    QFile *downloadedFile;  //下载保存的临时文件
public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    //自定义槽函数
    void do_finished();
    void do_readyRead();
    void do_downloadProgress(qint64 bytesRead, qint64 totalBytes);
    void on_btnDefaultPath_clicked();
    void on_btnDownload_clicked();
    void on_editURL_textChanged(const QString &arg1);
private:
    Ui::MainWindow *ui;
};

#endif // MAINWINDOW_H

在构造函数中设置UI后无须其他初始化设置

cpp 复制代码
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->editURL->setClearButtonEnabled(true);
}

设置默认下载保存路径

cpp 复制代码
void MainWindow::on_btnDefaultPath_clicked()
{//"默认路径"  按钮
    QString  curPath=QDir::currentPath();
    QDir    dir(curPath);
    QString  sub="temp";
    dir.mkdir(sub);    //创建一个临时文件夹
    ui->editPath->setText(curPath+"/"+sub+"/");
}

在输入有效的URL后点击下载对应的槽函数如下:

cpp 复制代码
void MainWindow::on_btnDownload_clicked()
{//"下载"按钮,开始下载
    QString urlSpec = ui->editURL->text().trimmed();
    if (urlSpec.isEmpty())
    {
        QMessageBox::information(this, "错误","请指定需要下载的URL");
        return;
    }
    QUrl newUrl = QUrl::fromUserInput(urlSpec);  //转为URL地址
    if (!newUrl.isValid())    //检查有效性
    {
        QString info="无效URL:"+urlSpec+"\n错误信息:"+newUrl.errorString();
        QMessageBox::information(this, "错误",info);
        return;
    }
    QString tempDir =ui->editPath->text().trimmed();    //临时目录
    if (tempDir.isEmpty())   //检查路径
    {
        QMessageBox::information(this, "错误", "请指定保存下载文件的目录");
        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, "错误","临时文件打开错误");
        return;
    }

    ui->btnDownload->setEnabled(false);
    //发送网络请求,创建网络响应
    reply = networkManager.get(QNetworkRequest(newUrl));
    //读取下载数据:在缓冲区有新下载的数据等待读取时,QNetworkReply 会发射 readyRead()信号
    connect(reply, SIGNAL(readyRead()), this, SLOT(do_readyRead()));
    //获取下载进度:传递 bytesRead 和 totalBytes 两个参数,表示已读取字节数和总的字节数
    connect(reply, SIGNAL(downloadProgress(qint64,qint64)),this, SLOT(do_downloadProgress(qint64,qint64)));
    //网络响应结束:信号 finished()在下载结束后被发射
    connect(reply, SIGNAL(finished()), this, SLOT(do_finished()));
}

1、首先读取URL文本框中的字符串,并判断是否为空,不为空再将该字符串使用QUrl::fromUserInput转为QUrl 类型变量,并检查URL的有效性。

2、检查下载保存的目录是否有效,trimmed()函数用于移除字符串两端的空白字符,如空格、制表符、换行符等

3、使用QUrl::fileName()获取下载连接中的文件名,并创建QFile临时文件用于暂存下载数据。

4、完成以上步骤后使用QNetworkAccessManager 对象发布网络请求,请求下载 URL 表示的文件, 并创建网络响应。

在缓冲区有新下载的数据等待读取时,QNetworkReply 会发射 readyRead()信号;信号 downloadProgress()表示网络操作进度,传递 bytesRead 和 totalBytes 两个参数,表示已读取字节数和总的字节数;信号 finished()在下载结束后被发射,通常再这个函数中关闭并删除临时文件指针对象,删除网络响应对象。

最后用静态函数 QDesktopServices::openUrl()调用默认的应用软件打开下载的文件,例如下载的是一个 PDF 文件,会自动用系统的默认软件打开此文件。

cpp 复制代码
void MainWindow::do_readyRead()
{//读取下载的数据
    downloadedFile->write(reply->readAll());
}

void MainWindow::do_downloadProgress(qint64 bytesRead, qint64 totalBytes)
{//下载进度
    ui->progressBar->setMaximum(totalBytes);
    ui->progressBar->setValue(bytesRead);
}

void MainWindow::do_finished()
{//网络响应结束
    QFileInfo fileInfo(downloadedFile->fileName());   //为了获取下载后的文件名

    downloadedFile->close();
    delete downloadedFile;   //删除临时文件对象
    reply->deleteLater(); //由主事件循环删除此对象

    if (ui->chkBoxOpen->isChecked())    //打开下载的文件
        QDesktopServices::openUrl(QUrl::fromLocalFile(fileInfo.absoluteFilePath()));
    ui->btnDownload->setEnabled(true);
}

参考

QT6 C++开发指南

相关推荐
白堤上的喵19 小时前
信息安全基础知识
网络
赖龙20 小时前
记录SSL部署,链路不完整问题
网络·网络协议·ssl
fatiaozhang952720 小时前
浪潮CD1000-移动云电脑-RK3528芯片-2+32G-安卓9-2种开启ADB ROOT刷机教程方法
android·网络·adb·电脑·电视盒子·刷机固件·机顶盒刷机
tang7778920 小时前
金融行业:静态与动态代理 IP 的选型与风控
网络·tcp/ip·金融
滴滴滴嘟嘟嘟.21 小时前
Qt对话框与文件操作学习
开发语言·qt·学习
Xの哲學21 小时前
Linux RCU (Read-Copy-Update) 机制深度分析
linux·网络·算法·架构·边缘计算
吐个泡泡v21 小时前
网络编程基础:一文搞懂 Socket、HTTP、HTTPS、TCP/IP、SSL 的关系
网络·网络协议·http·https·socket·ssl·tcp
liulilittle1 天前
HTTP简易客户端实现
开发语言·网络·c++·网络协议·http·编程语言
DreamLife☼1 天前
工业领域 ACP 协议全解析:从入门到实战案例
网络·安全·ai·工业·行为·acp·管控
滴滴滴嘟嘟嘟.1 天前
Qt图表功能学习
开发语言·qt·学习