【QT常用技能讲授】发送POST包(两种方式:壅闭方式及非壅闭方式)

[复制链接]
发表于 2025-11-23 20:01:16 | 显示全部楼层 |阅读模式
前言

        http/https(应用层)协议是广泛使用的网络通讯协议。在很多与第三方API对接的场景中,通常是通过http/https协议完成,好比API对接时,通常要通过POST包获取access_token举行鉴权,然后再举行数据交互(本篇也包罗有对吸收数据的json数据分析代码)。
        本篇以百度AI的API接口的access_token鉴权为例,通过QT特性QNetworkAccessManager实现两种方式的POST包方式:壅闭方式和非壅闭方式。
功能讲授

壅闭方式

        QT开辟的工具,通常没有高并发的网络通敬佩务需求,雷同原生socket一样,send完数据之后就(壅闭方式)recv数据,这好坏常广泛的调用方式,以下展示调用百度AI的API鉴权接口的过程。
  1. //头文件networkmanager.h
  2. #include <QNetworkAccessManager>
  3. #include <QNetworkRequest>
  4. #include <QNetworkReply>
  5. #include <QEventLoop>
  6. #include <QUrl>
  7. #include <QUrlQuery>
  8. #include <QJsonDocument>
  9. #include <QJsonObject>
  10. #include <QObject>
  11. #include <QDebug>
  12. #define API_KEY "GU1GeuGXNDhG48Z2aMYE2rD1"
  13. #define SECRET_KEY "NxrnIMZ7hi8vfIT734SiLhmwCpStEN8K"
  14. class NetworkManager : public QObject
  15. {
  16.     Q_OBJECT
  17. public:
  18.     explicit NetworkManager(QObject *parent = nullptr);
  19.     QByteArray  block_post_data(const QNetworkRequest& request,const QUrlQuery& postData);
  20.     QString get_access_token(const QString& client_id,const QString& client_secret) ;
  21. };
  22. //cpp文件networkmanager.cpp
  23. #include "networkmanager.h"
  24. NetworkManager::NetworkManager(QObject *parent) : QObject(parent)
  25. {
  26. }
  27. QByteArray NetworkManager::block_post_data(const QNetworkRequest& request,const QUrlQuery& postData){
  28.     //QString resstr;
  29.     QByteArray responseData;
  30.     // 创建网络访问管理器
  31.     QNetworkAccessManager block_manager;//这里不要用QNetworkAccessManager *block_manager的方式
  32.     // 发送POST请求
  33.     QNetworkReply* reply = block_manager.post(request, postData.toString(QUrl::FullyEncoded).toUtf8());
  34.     // 创建一个事件循环来阻塞当前线程
  35.     QEventLoop loop;
  36.     QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
  37.     // 阻塞当前线程直到网络请求完成
  38.     loop.exec();
  39.     // 检查请求结果
  40.     if (reply->error() == QNetworkReply::NoError) {
  41.         // 请求成功,处理返回的数据
  42.         /*QByteArray */responseData = reply->readAll();
  43.         //resstr = QString::fromUtf8(responseData);
  44.         //qDebug() << __LINE__ <<"Response:" << resstr;
  45.     } else {
  46.         // 请求失败,处理错误
  47.         qDebug() << "Error:" << reply->errorString();
  48.         responseData="";
  49.     }
  50.     // 清理
  51.     reply->deleteLater();
  52.     return responseData;
  53. }
  54. QString NetworkManager::get_access_token(const QString& client_id,const QString& client_secret) {
  55.     QString access_token;
  56.     QUrl url("https://aip.baidubce.com/oauth/2.0/token");
  57.     QNetworkRequest request(url);
  58.     request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
  59.     request.setRawHeader("Accept", "application/json");
  60.     // 创建 POST 数据
  61.     QUrlQuery postData;
  62.     postData.addQueryItem("grant_type", "client_credentials");
  63.     postData.addQueryItem("client_id", client_id);
  64.     postData.addQueryItem("client_secret", client_secret);
  65.     //发送Post包(通过阻塞方式获取返回结果)
  66.     QByteArray jsonData=block_post_data(request,postData);
  67.     // 解析 JSON 数据
  68.     QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData);
  69.     if (jsonDoc.isNull()) {
  70.         qDebug() << "Failed to create JSON doc.";
  71.         return "";
  72.     }
  73.     // 检查 JSON 文档类型
  74.     if (jsonDoc.isObject()) {
  75.         QJsonObject jsonObj = jsonDoc.object();
  76.         //qDebug() << "JSON Object:" << jsonObj;
  77.         // 访问 JSON 对象中的数据
  78.         if (jsonObj.contains("access_token")) {
  79.             access_token = jsonObj["access_token"].toString();
  80.             qDebug() << "access_token:" << access_token;
  81.         }
  82.     } else {
  83.         qDebug() << "JSON is not an object.";
  84.     }
  85.     return access_token;
  86. }
  87. //主函数文件main.cpp
  88. #include "networkmanager.h"
  89. #include <QApplication>
  90. int main(int argc, char *argv[])
  91. {
  92.     QApplication a(argc, argv);
  93.     NetworkManager networkManager;
  94.     QString access_token=networkManager.get_access_token(API_KEY,SECRET_KEY);
  95.     return a.exec();
  96. }
复制代码
以上代码中,调用QNetworkAccessManager的post之后,通过循环变瞎搅壅闭线程,直到获取到结果(QNetworkReply::finished)之后,才退失事故循环(QEventLoop::quit)。
  1.     // 创建一个事件循环来阻塞当前线程
  2.     QEventLoop loop;
  3.     QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
  4.     // 阻塞当前线程直到网络请求完成
  5.     loop.exec();
复制代码
除此之外,源代码还包罗了json分析部门,由于只有一个层级,直接获取access_token字段的内容即可。
  1. // 解析 JSON 数据
  2.     QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData);
  3.     if (jsonDoc.isNull()) {
  4.         qDebug() << "Failed to create JSON doc.";
  5.         return "";
  6.     }
  7.     // 检查 JSON 文档类型
  8.     if (jsonDoc.isObject()) {
  9.         QJsonObject jsonObj = jsonDoc.object();
  10.         //qDebug() << "JSON Object:" << jsonObj;
  11.         // 访问 JSON 对象中的数据
  12.         if (jsonObj.contains("access_token")) {//-----json格式中最外层的access_token字段
  13.             access_token = jsonObj["access_token"].toString();
  14.             qDebug() << "access_token:" << access_token;
  15.         }
  16.     } else {
  17.         qDebug() << "JSON is not an object.";
  18.     }
复制代码
非壅闭方式

        在计划时,假如异步处置惩罚更加符合框架的处置惩罚性能需求时,好比鉴权完成之后,批量调用百度AI的OCR接口时,批量的组装并发送POST包,然后异步的吸收数据之后,生存到当地(大概是抽取关键数据)的场景时,就得用异步的方式,以下只是展示调用百度AI的API鉴权接口来贴源代码。
  1. //头文件networkmanager.h
  2. #include <QNetworkAccessManager>
  3. #include <QNetworkRequest>
  4. #include <QNetworkReply>
  5. #include <QUrl>
  6. #include <QByteArray>
  7. #include <QUrlQuery>
  8. #include <QJsonDocument>
  9. #include <QJsonObject>
  10. #include <QObject>
  11. #include <QDebug>
  12. #define API_KEY "GU1GeuGXNDhG48Z2aMYE2rD1"
  13. #define SECRET_KEY "NxrnIMZ7hi8vfIT734SiLhmwCpStEN8K"
  14. class NetworkManager : public QObject
  15. {
  16.     Q_OBJECT
  17. public:
  18.     explicit NetworkManager(QObject *parent = nullptr);
  19.     void get_access_token(const QString& client_id,const QString& client_secret) ;
  20. private slots:
  21.     void onFinished(QNetworkReply *reply);
  22. private:
  23.     QNetworkAccessManager *manager;
  24. };
  25. --------------------------------------------------------------------------
  26. //cpp文件networkmanager.cpp
  27. #include "networkmanager.h"
  28. NetworkManager::NetworkManager(QObject *parent) : QObject(parent)
  29. {
  30.     manager = new QNetworkAccessManager(this);
  31.     connect(manager, &QNetworkAccessManager::finished, this, &NetworkManager::onFinished);//接收数据的槽函数
  32. }
  33. void NetworkManager::get_access_token(const QString& client_id,const QString& client_secret) {
  34.     QUrl url("https://aip.baidubce.com/oauth/2.0/token");
  35.     QNetworkRequest request(url);
  36.     request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
  37.     request.setRawHeader("Accept", "application/json");
  38.     // 创建 POST 数据
  39.     QUrlQuery postData;
  40.     postData.addQueryItem("grant_type", "client_credentials");
  41.     postData.addQueryItem("client_id", client_id);
  42.     postData.addQueryItem("client_secret", client_secret);
  43.     // 发送 POST 请求
  44.     //manager->post(request, jsonData);
  45.     // 发送 POST 请求
  46.     manager->post(request, postData.toString(QUrl::FullyEncoded).toUtf8());
  47. }
  48. void NetworkManager::onFinished(QNetworkReply *reply) {
  49.     if (reply->error() == QNetworkReply::NoError) {
  50.         QByteArray responseData = reply->readAll();
  51.         qDebug() << "Response:" << responseData;
  52.     } else {
  53.         qDebug() << "Error:" << reply->errorString();
  54.     }
  55.     reply->deleteLater();
  56. }
  57. //主函数main.cpp
  58. #include <QApplication>
  59. #include "networkmanager.h"
  60. int main(int argc, char *argv[])
  61. {
  62.     QApplication a(argc, argv);
  63.     NetworkManager networkManager;
  64.     networkManager.get_access_token(API_KEY,SECRET_KEY);
  65.     return a.exec();
  66. }
复制代码
源码中通过信号和槽机制,同一获取并处置惩罚Post的返回结果。
  1. //通过信号和槽机制,统一获取并处理Post的返回结果
  2. manager = new QNetworkAccessManager(this);
  3. connect(manager, &QNetworkAccessManager::finished, this, &NetworkManager::onFinished);
  4. void NetworkManager::onFinished(QNetworkReply *reply) {
  5.     if (reply->error() == QNetworkReply::NoError) {
  6.         QByteArray responseData = reply->readAll();
  7.         qDebug() << "Response:" << responseData;
  8.     } else {
  9.         qDebug() << "Error:" << reply->errorString();
  10.     }
  11.     reply->deleteLater();
  12. }
复制代码
片尾

        由于百度API是https调用的,QT环境须要专门匹配的SSL版原来支持,假如没有对应的动态文件,编译时会如下报错:

以下提供一个传送门:
办理qt.network.ssl 和 OpenSSL 1.1.1g Win64版本EXE下载

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

×
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表