前言
http/https(应用层)协议是广泛使用的网络通讯协议。在很多与第三方API对接的场景中,通常是通过http/https协议完成,好比API对接时,通常要通过POST包获取access_token举行鉴权,然后再举行数据交互(本篇也包罗有对吸收数据的json数据分析代码)。
本篇以百度AI的API接口的access_token鉴权为例,通过QT特性QNetworkAccessManager实现两种方式的POST包方式:壅闭方式和非壅闭方式。
功能讲授
壅闭方式
QT开辟的工具,通常没有高并发的网络通敬佩务需求,雷同原生socket一样,send完数据之后就(壅闭方式)recv数据,这好坏常广泛的调用方式,以下展示调用百度AI的API鉴权接口的过程。
- //头文件networkmanager.h
- #include <QNetworkAccessManager>
- #include <QNetworkRequest>
- #include <QNetworkReply>
- #include <QEventLoop>
- #include <QUrl>
- #include <QUrlQuery>
- #include <QJsonDocument>
- #include <QJsonObject>
- #include <QObject>
- #include <QDebug>
- #define API_KEY "GU1GeuGXNDhG48Z2aMYE2rD1"
- #define SECRET_KEY "NxrnIMZ7hi8vfIT734SiLhmwCpStEN8K"
- class NetworkManager : public QObject
- {
- Q_OBJECT
- public:
- explicit NetworkManager(QObject *parent = nullptr);
- QByteArray block_post_data(const QNetworkRequest& request,const QUrlQuery& postData);
- QString get_access_token(const QString& client_id,const QString& client_secret) ;
- };
- //cpp文件networkmanager.cpp
- #include "networkmanager.h"
- NetworkManager::NetworkManager(QObject *parent) : QObject(parent)
- {
- }
- QByteArray NetworkManager::block_post_data(const QNetworkRequest& request,const QUrlQuery& postData){
- //QString resstr;
- QByteArray responseData;
- // 创建网络访问管理器
- QNetworkAccessManager block_manager;//这里不要用QNetworkAccessManager *block_manager的方式
- // 发送POST请求
- QNetworkReply* reply = block_manager.post(request, postData.toString(QUrl::FullyEncoded).toUtf8());
- // 创建一个事件循环来阻塞当前线程
- QEventLoop loop;
- QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
- // 阻塞当前线程直到网络请求完成
- loop.exec();
- // 检查请求结果
- if (reply->error() == QNetworkReply::NoError) {
- // 请求成功,处理返回的数据
- /*QByteArray */responseData = reply->readAll();
- //resstr = QString::fromUtf8(responseData);
- //qDebug() << __LINE__ <<"Response:" << resstr;
- } else {
- // 请求失败,处理错误
- qDebug() << "Error:" << reply->errorString();
- responseData="";
- }
- // 清理
- reply->deleteLater();
- return responseData;
- }
- QString NetworkManager::get_access_token(const QString& client_id,const QString& client_secret) {
- QString access_token;
- QUrl url("https://aip.baidubce.com/oauth/2.0/token");
- QNetworkRequest request(url);
- request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
- request.setRawHeader("Accept", "application/json");
- // 创建 POST 数据
- QUrlQuery postData;
- postData.addQueryItem("grant_type", "client_credentials");
- postData.addQueryItem("client_id", client_id);
- postData.addQueryItem("client_secret", client_secret);
- //发送Post包(通过阻塞方式获取返回结果)
- QByteArray jsonData=block_post_data(request,postData);
- // 解析 JSON 数据
- QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData);
- if (jsonDoc.isNull()) {
- qDebug() << "Failed to create JSON doc.";
- return "";
- }
- // 检查 JSON 文档类型
- if (jsonDoc.isObject()) {
- QJsonObject jsonObj = jsonDoc.object();
- //qDebug() << "JSON Object:" << jsonObj;
- // 访问 JSON 对象中的数据
- if (jsonObj.contains("access_token")) {
- access_token = jsonObj["access_token"].toString();
- qDebug() << "access_token:" << access_token;
- }
- } else {
- qDebug() << "JSON is not an object.";
- }
- return access_token;
- }
- //主函数文件main.cpp
- #include "networkmanager.h"
- #include <QApplication>
- int main(int argc, char *argv[])
- {
- QApplication a(argc, argv);
- NetworkManager networkManager;
- QString access_token=networkManager.get_access_token(API_KEY,SECRET_KEY);
- return a.exec();
- }
复制代码 以上代码中,调用QNetworkAccessManager的post之后,通过循环变瞎搅壅闭线程,直到获取到结果(QNetworkReply::finished)之后,才退失事故循环(QEventLoop::quit)。
- // 创建一个事件循环来阻塞当前线程
- QEventLoop loop;
- QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);
- // 阻塞当前线程直到网络请求完成
- loop.exec();
复制代码 除此之外,源代码还包罗了json分析部门,由于只有一个层级,直接获取access_token字段的内容即可。
- // 解析 JSON 数据
- QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonData);
- if (jsonDoc.isNull()) {
- qDebug() << "Failed to create JSON doc.";
- return "";
- }
- // 检查 JSON 文档类型
- if (jsonDoc.isObject()) {
- QJsonObject jsonObj = jsonDoc.object();
- //qDebug() << "JSON Object:" << jsonObj;
- // 访问 JSON 对象中的数据
- if (jsonObj.contains("access_token")) {//-----json格式中最外层的access_token字段
- access_token = jsonObj["access_token"].toString();
- qDebug() << "access_token:" << access_token;
- }
- } else {
- qDebug() << "JSON is not an object.";
- }
复制代码 非壅闭方式
在计划时,假如异步处置惩罚更加符合框架的处置惩罚性能需求时,好比鉴权完成之后,批量调用百度AI的OCR接口时,批量的组装并发送POST包,然后异步的吸收数据之后,生存到当地(大概是抽取关键数据)的场景时,就得用异步的方式,以下只是展示调用百度AI的API鉴权接口来贴源代码。
- //头文件networkmanager.h
- #include <QNetworkAccessManager>
- #include <QNetworkRequest>
- #include <QNetworkReply>
- #include <QUrl>
- #include <QByteArray>
- #include <QUrlQuery>
- #include <QJsonDocument>
- #include <QJsonObject>
- #include <QObject>
- #include <QDebug>
- #define API_KEY "GU1GeuGXNDhG48Z2aMYE2rD1"
- #define SECRET_KEY "NxrnIMZ7hi8vfIT734SiLhmwCpStEN8K"
- class NetworkManager : public QObject
- {
- Q_OBJECT
- public:
- explicit NetworkManager(QObject *parent = nullptr);
- void get_access_token(const QString& client_id,const QString& client_secret) ;
- private slots:
- void onFinished(QNetworkReply *reply);
- private:
- QNetworkAccessManager *manager;
- };
- --------------------------------------------------------------------------
- //cpp文件networkmanager.cpp
- #include "networkmanager.h"
- NetworkManager::NetworkManager(QObject *parent) : QObject(parent)
- {
- manager = new QNetworkAccessManager(this);
- connect(manager, &QNetworkAccessManager::finished, this, &NetworkManager::onFinished);//接收数据的槽函数
- }
- void NetworkManager::get_access_token(const QString& client_id,const QString& client_secret) {
- QUrl url("https://aip.baidubce.com/oauth/2.0/token");
- QNetworkRequest request(url);
- request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
- request.setRawHeader("Accept", "application/json");
- // 创建 POST 数据
- QUrlQuery postData;
- postData.addQueryItem("grant_type", "client_credentials");
- postData.addQueryItem("client_id", client_id);
- postData.addQueryItem("client_secret", client_secret);
- // 发送 POST 请求
- //manager->post(request, jsonData);
- // 发送 POST 请求
- manager->post(request, postData.toString(QUrl::FullyEncoded).toUtf8());
- }
- void NetworkManager::onFinished(QNetworkReply *reply) {
- if (reply->error() == QNetworkReply::NoError) {
- QByteArray responseData = reply->readAll();
- qDebug() << "Response:" << responseData;
- } else {
- qDebug() << "Error:" << reply->errorString();
- }
- reply->deleteLater();
- }
- //主函数main.cpp
- #include <QApplication>
- #include "networkmanager.h"
- int main(int argc, char *argv[])
- {
- QApplication a(argc, argv);
- NetworkManager networkManager;
- networkManager.get_access_token(API_KEY,SECRET_KEY);
- return a.exec();
- }
复制代码 源码中通过信号和槽机制,同一获取并处置惩罚Post的返回结果。
- //通过信号和槽机制,统一获取并处理Post的返回结果
- manager = new QNetworkAccessManager(this);
- connect(manager, &QNetworkAccessManager::finished, this, &NetworkManager::onFinished);
- void NetworkManager::onFinished(QNetworkReply *reply) {
- if (reply->error() == QNetworkReply::NoError) {
- QByteArray responseData = reply->readAll();
- qDebug() << "Response:" << responseData;
- } else {
- qDebug() << "Error:" << reply->errorString();
- }
- reply->deleteLater();
- }
复制代码 片尾
由于百度API是https调用的,QT环境须要专门匹配的SSL版原来支持,假如没有对应的动态文件,编译时会如下报错:
以下提供一个传送门:
办理qt.network.ssl 和 OpenSSL 1.1.1g Win64版本EXE下载
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |