QT发起http/https请求

发布时间 2023-11-07 12:48:52作者: 黄河大道东

示例

1、在.pro工程描述文件中添加网络模块

QT += network

2、示例代码

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "ui_mainwindow.h"
#include "QDebug"

#include <QWidget>
#include <QObject>
#include <QDebug>
#include <QHttpMultiPart>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QMetaObject>
#include <QEventLoop>
// 以下是json数据传送所需头文件
#include <QJsonDocument>
#include <QJsonParseError>
#include <QJsonObject>
#include <QJsonValue>
#include <QJsonArray>
#include <QVariant>

QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE

class MainWindow : public QMainWindow {
    Q_OBJECT

  public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow(){ delete ui; };
    // 发送 http/https 的 GET 请求
    void doGet(QString &url,QString &contentType) {
        // 1、构建网络请求对象
        QNetworkRequest req;
        req.setUrl(QUrl(url));
        req.setHeader(QNetworkRequest::ContentTypeHeader,QVariant(contentType));
        // 2、构建网络访问管理器
        QNetworkAccessManager nam;
        // 3、连接 网络访问管理器的 finished 信号与当前 QWidget 组件的匿名槽函数,作用是打印响应内容
        connect(&nam, &QNetworkAccessManager::finished, this, [](QNetworkReply *reply) {
            QString res = reply->readAll();
            qDebug() << res;
        });
        // 4、发起 GET 请求
        QNetworkReply *resp = nam.get(req);
        // 5、构建事件循环对象
        QEventLoop loop;
        // 6、连接 网络响应对象的 finished 信号与事件循环 的退出事件循环槽函数
        connect(resp,&QNetworkReply::finished,&loop,&QEventLoop::quit);
        // 7、开启事件循环
        loop.exec();
    }

    // 发送一个 http/https 的 POST 请求
    void doPost(QJsonObject &body,QString &url,QString &contentType) {
        // 0、处理 POST 请求的 body
        QJsonDocument document;
        document.setObject(body);
        // 1、将请求 json 转换为字节组
        QByteArray byte_array = document.toJson(QJsonDocument::Compact);
        // 2、构建网络请求对象
        QNetworkRequest req;
        req.setUrl(QUrl(url));
        req.setHeader(QNetworkRequest::ContentTypeHeader,QVariant(contentType));
        // 3、构建网络访问管理器
        QNetworkAccessManager nam;
        // 4、连接 网络访问管理器的 finished 信号与当前 QWidget 组件的匿名槽函数,作用是打印响应内容
        connect(&nam, &QNetworkAccessManager::finished, this, [](QNetworkReply *reply) {
            QString res = reply->readAll();
            qDebug() << res;
        });
        // 5、发起 POST 请求 + 传输的数据
        QNetworkReply* reply = nam.post(req, byte_array);
        // 6、构建事件循环对象
        QEventLoop loop;
        // 7、连接 网络响应对象的 finished 信号与事件循环 的退出事件循环槽函数
        connect(reply,&QNetworkReply::finished,&loop,&QEventLoop::quit);
        // 8、开启事件循环
        loop.exec();
    }
  private:
    Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H

注意:connect()连接函数只能在 QObject 对象之间中使用

3、测试

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "QString"
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) {
    ui->setupUi(this);
    QString url = "https://blog.csdn.net/qq_39153720/article/details/122118492";
    QString contentType = "application/json;charset=utf-8";
    // 发起 GET 请求测试
    this->doGet(url,contentType);
    QJsonObject body;
    // 发起 POST 请求测试
    this->doPost(body,url,contentType);
}

开启SSL

  Qt 使用QNetwork 模块,进行api请求时发生错误,错误信息:qt.network.ssl: QSslSocket::connectToHostEncrypted: TLS initialization failed

  Qt本身是支持ssl的,但是因为法律原因?没有自带对应的dll,先使下方代码打印当前Qt版本支持的SSL版本

解决:

#include <QSslSocket>
#include <QDebug>
qDebug()<< QSslSocket::sslLibraryBuildVersionString();		// "OpenSSL 1.1.1d  10 Sep 2019"

接下来就去下载对应版本的OpenSSL

  • 方式一

  下载OpenSSL源码,自行编译:https://www.openssl.org/source/

  • 方式二

  直接下载 dll :https://slproweb.com/products/Win32OpenSSL.html

  这里推荐第二个方法,省去自己编译的时间。然后在这个网站找到对应的版本,比如刚刚打印的1.1.1,同时,也要注意工程是32位还是64位,这里选择的是Win64 OpenSSL v1.1.1n Light至于EXE还是MSI都没差异。

image

安装的时候选择的是第二个,这样可以方便的进行 dll 文件的拷贝

image

进入OpenSSL安装目录。bin目录下,拷贝这两个dll文件到工程的exe程序所在路径下

image

比如这里的路径,直接放到exe 可执行文件的根路径下即可,然后程序即可正常运行。注意下方图片中黄色框出来的是旧版本的 dll ,因为有的人Qt版本可能比较低,那么打印出来的 OpenSSL 版本可能是1.0.2,那么dll名字大概率就是黄色框中的那样。

image

  注意:这里也测试了一下,不同OpenSSL版本的dll是否可以通用,发现高低版本都不行,必须和 Qt 打印出来的OpenSSL版本一致才行。
  很多帖子都说把这两个dll文件放到E:\QT\5.12.3\mingw73_64\bin路径下,即Qt的安装路径下。这样也可以,但是我觉得不好,个人认为尽量别去动Qt安装路径下的文件,尽量避免人为改变QT的默认开发环境,主要是为了以后排错不会导致当时自己把文件放到了Qt安装路径下太久忘记,而在别的电脑上无法正常使用的情况。

参考

QT进行http请求(post/get)

https://blog.csdn.net/qq_63986699/article/details/124998384

Qt 解决qt.network.ssl: QSslSocket::connectToHostEncrypted: TLS initialization failed问题

https://blog.csdn.net/WHEgqing/article/details/129836181

https://blog.csdn.net/BadAyase/article/details/103905615