赞
踩
在使用qt做http通讯前,我们得先学习了解http。我们从以下几个方面来了解http。
根据 HTTP 标准,HTTP 请求可以使用多种请求方法。
HTTP1.0 定义了三种请求方法: GET, POST 和 HEAD 方法。
HTTP1.1 新增了六种请求方法:OPTIONS、PUT、PATCH、DELETE、TRACE 和 CONNECT 方法。
序号 | 方法 | 描述 |
---|---|---|
1 | GET | 请求指定的页面信息,并返回实体主体。 |
2 | HEAD | 类似于 GET 请求,只不过返回的响应中没有具体的内容,用于获取报头 |
3 | POST | 向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST 请求可能会导致新的资源的建立和/或已有资源的修改。 |
4 | PUT | 从客户端向服务器传送的数据取代指定的文档的内容。 |
5 | DELETE | 请求服务器删除指定的页面。 |
6 | CONNECT | HTTP/1.1 协议中预留给能够将连接改为管道方式的代理服务器。 |
7 | OPTIONS | 允许客户端查看服务器的性能。 |
8 | TRACE | 回显服务器收到的请求,主要用于测试或诊断。 |
9 | PATCH | 是对 PUT 方法的补充,用来对已知资源进行局部更新 |
我们平时使用的基本是GET、POST、PUT。
根据结构http可看作由URL、HEAD、BODY组成。
每个部分都可以有相应的参数。
url参数直接放在url连接里,它们是以符号?开始,以&为分隔符的键值对。例如
http://example.com/api?param1=value1¶m2=value2
其中param1和param2是参数名,value1和value2是值。
在QT中赋值:
QUrl url("http://example.com/api");
QUrlQuery query;
query.addQueryItem("param1", "value1");
query.addQueryItem("param2", "value2");
url.setQuery(query);
或者直接像上面例子中,直接把参数写进url地址里
QUrl url("http://example.com/api?param1=value1¶m2=value2");
Header参数是通过HTTP请求的Header部分传递的参数。Header参数包含在HTTP请求的Header字段中,以键值对的形式传递。
在Qt中,使用QNetworkRequest类进行设置。
一般会让我们设置Content-Type参数,如下面的API文档中
参数 | 值 |
---|---|
Content-Type | application/x-www-form-urlencoded |
在Qt中可以这样设置:
QNetworkRequest request(token);
request.setHeader(QNetworkRequest::ContentTypeHeader,"application/x-www-form-urlencoded");
关于Content-Type参数的作用:
在HTTP通信中,Content-Type参数用于指定请求或响应中所传输数据的MIME类型(Multipurpose Internet Mail Extensions,多用途Internet Mail扩展)。不同的Content-Type参数会告诉接收方如何解析和处理数据。
Content-Type类型与对应的解释见下表:
常见的媒体格式类型如下:
text/html : HTML格式
text/plain :纯文本格式
text/xml : XML格式
image/gif :gif图片格式
image/jpeg :jpg图片格式
image/png:png图片格式
以application开头的媒体格式类型:
application/xhtml+xml :XHTML格式
application/xml: XML数据格式
application/atom+xml :Atom XML聚合格式
application/json: JSON数据格式
application/pdf:pdf格式
application/msword : Word文档格式
application/octet-stream : 二进制流数据(如常见的文件下载)
application/x-www-form-urlencoded :form表单数据被编码为key/value格式发送到服务器(表单默认的提交数据的格式)
另外一种常见的媒体格式是上传文件之时使用的:
multipart/form-data : 需要在表单中进行文件上传时,就需要使用该格式
Qt中对于不同类型的Content-Type,对数据的处理方式如下:
{
"name": "John Doe",
"age": 30,
"email": "johndoe@example.com"
}
//注意此时的base64中的/+符号不需要转化
name=John%20Doe&age=30&email=johndoe%40example.com
//注意此时的base64中的/+符号需要转化
--boundary
Content-Disposition: form-data; name="name"
John Doe
--boundary
Content-Disposition: form-data; name="file"; filename="example.txt"
Content-Type: text/plain
This is a sample file.
--boundary--
name: John Doe
age: 30
email: johndoe@example.com
Body参数是通过HTTP请求的消息正文(Body)中传递的参数。这种方式常用于POST、PUT等需要传递大量数据的请求。在Qt中,可以使用QNetworkAccessManager类来发送HTTP请求,并通过QByteArray或QHttpMultiPart来设置和发送Body参数。
这里我们只介绍用QByteArray来设置body参数,因为后者只是比前者多了几个步骤。
QByteArray bodyData = "param1=value1¶m2=value2";
···
QNetworkReply *reply = manager.post(request, bodyData);
//request为上面的QNetworkRequest,manager是QNetworkAccessManager
具体的使用方法我们下面会介绍。
QNetworkAccessManager:http中最主要的类,负责对http请求的get、post等操作。
QNetworkRequest:http请求体类,包含head信息、body信息。
QUrl:存放url信息。
QNetworkReply:负责接收http返回消息。
QJsonDocument:json文档。
QJsonObject:json对象。
QJsonValue:json值。
本文以百度api的图像无损放大为例,api文档连接:百度API图像无损放大
请求说明
请求示例
HTTP 方法:POST
请求URL: https://aip.baidubce.com/rest/2.0/image-process/v1/image_quality_enhance
URL参数:
参数 值
access_token 通过API Key和Secret Key获取的access_token,参考“Access Token获取”
首先文档最开头规定了http方法为POST,并且告诉我们URL地址
这里的access_token参数需要我们单独去获取。
access_token的获取比较简单,只需要设置url参数即可。Qt中例子如下
manager = new QNetworkAccessManager;
QUrl token("https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=你自己的apikey&client_secret=你自己的secretkey");
QNetworkRequest request(token);
request.setHeader(QNetworkRequest::ContentTypeHeader,"application/json");
QByteArray ba;
QNetworkReply *reply = manager->post(request,ba);
while (!reply->isFinished()) {
qApp->processEvents();
}
QByteArray res = reply->readAll();
QJsonDocument doc = QJsonDocument::fromJson(res);
QJsonObject obj = doc.object();
QJsonValue va = obj.value("access_token");
QString access_token = va.toString();
我们回到图像放大的文档。根据刚才获取到的access_token,可以完成url和head的设置。
QUrl url("https://aip.baidubce.com/rest/2.0/image-process/v1/image_quality_enhance?access_token="+access_token);
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::ContentTypeHeader,"application/x-www-form-urlencoded");
继续往下,设置body数据
文档中body数据是image和url二选一,先选第一个。参数名为image,值为图片的base64编码形式。
QImage image("image.png");
QByteArray byteArray;
QBuffer buffer(&byteArray);
buffer.open(QIODevice::WriteOnly);
image.save(&buffer, "PNG"); // 可以根据需要选择其他格式,如JPEG
QString base64 = byteArray.toBase64();
我一开始调试接口时总是失败,百度返给我的失败信息是图片格式错误,我用官方调试平台生产的base64和自己本地比较,发现有些地方不一样,我自己生成的base64会带有一些符号,比如"/“,”+“,需要转化成url能接受的符号,比如”/“是”%2F",“+“是”%3D”,我用QString::replace进行替换后就成功了,后来发现QUrl类中自带了一个方法,能把字符串处理成url可接受的格式。在Content-Type类型为application/x-www-form-urlencoded时,需要把符号转化。
所以上面的最后一行代码修改为:
QString base64 = QUrl::toPercentEncoding(byteArray.toBase64());
QByteArray ba = "image="+base64.toLatin1();
QNetworkReply *reply = manager->post(request,ba);
while (!reply->isFinished()) {
qApp->processEvents();
}
QByteArray res_ba = reply->readAll();
QJsonDocument res_doc = QJsonDocument::fromJson(res_ba);
QJsonObject res_obj = res_doc.object();
QJsonValue img = res_obj.value("image");
QString base64 = img.toString();
QPixmap pix;
pix.loadFromData(QByteArray::fromBase64(base64.toLatin1()));
pix.save("D:/test.jpg","jpg");
widget.h
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QUrl>
#include <QNetworkReply>
#include <QDebug>
#include <QFileDialog>
#include <QBuffer>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonValue>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget *parent = nullptr);
~Widget();
private slots:
void on_open1_clicked();
void on_zoomin_clicked();
private:
Ui::Widget *ui;
QNetworkAccessManager *manager;
QString access_token;
QString pic1;
};
#endif // WIDGET_H
widget.cpp
#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
manager = new QNetworkAccessManager;
QUrl token("https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id=***&client_secret=***");
QNetworkRequest request(token);
request.setHeader(QNetworkRequest::ContentTypeHeader,"application/json");
QByteArray ba;
QNetworkReply *reply = manager->post(request,ba);
while (!reply->isFinished()) {
qApp->processEvents();
}
QByteArray res = reply->readAll();
QJsonDocument doc = QJsonDocument::fromJson(res);
QJsonObject obj = doc.object();
QJsonValue va = obj.value("access_token");
access_token = va.toString();
qDebug()<<access_token;
}
Widget::~Widget()
{
delete ui;
}
void Widget::on_open1_clicked()
{
QString filename = QFileDialog::getOpenFileName(this,"open file","./","*.png *.jpg");
QFile file(filename);
QImage img;
img.load(filename);
QByteArray ba;
QBuffer bf(&ba);
bf.open(QIODevice::WriteOnly);
img.save(&bf,"jpg");
pic1 = QUrl::toPercentEncoding(ba.toBase64());
bf.close();
}
void Widget::on_zoomin_clicked()
{
QUrl url("https://aip.baidubce.com/rest/2.0/image-process/v1/image_quality_enhance?access_token="+access_token);
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::ContentTypeHeader,"application/x-www-form-urlencoded");
QByteArray ba = "image="+pic1.toLatin1();
QNetworkReply *reply = manager->post(request,ba);
while (!reply->isFinished()) {
qApp->processEvents();
}
QByteArray res_ba = reply->readAll();
QJsonDocument res_doc = QJsonDocument::fromJson(res_ba);
QJsonObject res_obj = res_doc.object();
QJsonValue img = res_obj.value("image");
QString base64 = img.toString();
QPixmap pix;
pix.loadFromData(QByteArray::fromBase64(base64.toLatin1()));
pix.save("D:/test.jpg","jpg");
}
本例子中由于参数较少,直接用QByteArray装载了字符串。当参数多尤其是结构有多层时,应该用json。下面是人脸融合api的参数示例:
参数 | 必选 | 类型 | 说明 |
---|---|---|---|
version | 否 | string | 服务版本 ,可选(1.0,2.0,3.0,4.0),如不传入该项则默认调用(1.0),2.0/3.0/4.0对merge_degree不生效,对融合效果要求较高可选择2.0(推荐版本),对融合结果的清晰度要求较高可选择3.0,4.0为最新版本,清晰度及融合效果均有提升,页面功能演示为2.0版本效果 |
alpha | 否 | float | 融合参数,可选范围 0-1浮点数,保留两位小数,默认(0), 只在version=4.0时才有效。0代表与目标图人脸最大程度相似(完全换脸),1 代表完全不换脸保留模版图,中间值(如0.5)为进行一般的换脸效果。该参数主要用于连续使用制作一组换脸渐变图片 |
image_template | 是 | object | 模板图信息,要求被融合的人脸 边缘需要与图片边缘保持一定距离, 图片要求见文档底部 |
+image | 是 | string | 模板图信息 图片的分辨率要求在1920x1080以下 |
+image_type | 是 | string | 图片类型 BASE64:图片的base64值; URL:图片的 URL( 下载图片时可能由于网络等原因导致下载图片时间过长) FACE_TOKEN: 人脸标识 |
+quality_control | 否 | string | 质量控制 NONE: 不进行控制 LOW:较低的质量要求 NORMAL: 一般的质量要求 HIGH: 较高的质量要求 默认NONE |
+face_location | 否 | string | 指定模板图中进行人脸融合的人脸框位置 不指定时则默认使用最大的人脸 格式形如: {\"left\": 111.4,\"top\": 96.56,\"width\": 98,\"height\": 98,\"rotation\": 3} 当image_type为FACE_TOKEN时, 此参数无效, 会使用FACE_TOKEN对应的人脸 |
image_target | 是 | object | 目标图信息,要求图片为清晰正脸 |
+image | 是 | string | 目标图信息 图片的分辨率要求在1920x1080以下 |
+image_type | 是 | string | 图片类型 BASE64:图片的base64值; URL:图片的 URL( 下载图片时可能由于网络等原因导致下载图片时间过长) FACE_TOKEN: 人脸标识 |
+quality_control | 否 | string | 质量控制 NONE: 不进行控制 LOW:较低的质量要求 NORMAL: 一般的质量要求 HIGH: 较高的质量要求 默认NONE |
+face_location | 否 | string | 指定目标图中进行人脸融合的人脸框位置 不指定时则默认使用最大的人脸 格式形如: {\"left\": 111.4,\"top\": 96.56,\"width\": 98,\"height\": 98,\"rotation\": 3} 当image_type为FACE_TOKEN时, 此参数无效, 会使用FACE_TOKEN对应的人脸 |
merge_degree | 否 | string | 融合度 关系到融合图与目标图的相似度 越高则越相似 LOW:较低的融合度 NORMAL: 一般的融合度 HIGH: 较高的融合度 COMPLETE: 完全融合 默认COMPLETE |
position | 否 | int | 水印的位置,取值如下: 0-右下角 1-左下角 2-左上角 3-右上角 默认0 |
language | 否 | int | 水印的语言,取值如下: 0-中文(AI生成) 1-英文(Generated by AI) 默认0 |
QUrl url("https://aip.baidubce.com/rest/2.0/face/v1/merge?access_token="+access_token);
QNetworkRequest request(url);
request.setHeader(QNetworkRequest::ContentTypeHeader,"application/json");
QJsonObject obj;
obj.insert("version","4.0");
QJsonObject img_template;
img_template.insert("image",pic1);
img_template.insert("image_type","BASE64");
QJsonObject img_target;
img_target.insert("image",pic2);
img_target.insert("image_type","BASE64");
obj.insert("image_template",img_template);
obj.insert("image_target",img_target);
QJsonDocument doc;
doc.setObject(obj);
QByteArray ba=doc.toJson(QJsonDocument::Compact);
QNetworkReply *reply = manager->post(request,ba);
while (!reply->isFinished()) {
qApp->processEvents();
}
QByteArray res = reply->readAll();
QJsonDocument json_res = QJsonDocument::fromJson(res);
QJsonObject json_obj = doc.object();
QJsonObject jv = json_obj["result"].toObject();
QJsonValue img = jv.value("merge_image");
QString base64pic = img.toString();
QPixmap pix;
pix.loadFromData(QByteArray::fromBase64(base64pic.toLatin1()));
ui->face3->setPixmap(pix);
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。