Qt之QHttpPart和QHttpMultiPart

简介: 简述HTTP 协议对 MIME 类型有详细描述,multipart/... 是单个消息头包含多个消息体的解决方案,multipart 类型对发送非文本类型非常有用。简述multipart 子类型QHttpPartQHttpMultiPart使用示例multipart 子类型首先,来看 QHttpMultiPart 中关于 multi

简述

HTTP 协议对 MIME 类型有详细描述,multipart/... 是单个消息头包含多个消息体的解决方案,multipart 类型对发送非文本类型非常有用。

multipart 子类型

首先,来看 QHttpMultiPart 中关于 multipart 子类型(subtype)的描述。

枚举 QHttpMultiPart::ContentType

RFC 2046 和其它地方描述的已知 multipart 子类型。

常量 描述
QHttpMultiPart::MixedType 0 对应于 "multipart/mixed" 子类型,意味着 body 部位是相互独立的。如 RFC 2046 所述。
QHttpMultiPart::RelatedType 1 对应于 "multipart/related" 子类型,意味着 body 部位是相互关联的。如 RFC 2387 所述。
QHttpMultiPart::FormDataType 2 对应 "multipart/form-data" 子类型,意味着 body 部位包含表单元素。如 RFC 2388 所述。
QHttpMultiPart::AlternativeType 3 对应 "multipart/alternative" 子类型,意味着 body 部位是相同信息的替代表示。如 RFC 2046 所述。

QHttpPart

QHttpPart 类拥有一个 body 部位,用于 HTTP multipart MIME消息中(由 QHttpMultiPart 表示)。一个 QHttpPart 由一个 header 块和数据块组成,彼此之间存在两个连续换行。

一个 part 例子:

Content-Type: text/plain
Content-Disposition: form-data; name="text"

here goes the body
AI 代码解读

要设置 headers,使用 setHeader() 和 setRawHeader(),他们完全类似于 QNetworkRequest::setHeader() 和 QNetworkRequest::setRawHeader()。

对于读取小数据块,使用 setBody();如果是更大数据块,例如:图像,使用 setBodyDevice()。后一种方法由于内部没有复制数据,而是直接从设备读取,所以更节省内存。这意味着,当由 QNetworkAccessManager::post() 在网络上发送包含 body 部分的 multipart 消息时,设备必须打开并且可读。

构建一个小 body 的 QHttpPart,考虑下面的代码片段(将产生上述示例中显示的数据):

QHttpPart textPart;
textPart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("text/plain"));
textPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"text\""));
textPart.setBody("here goes the body");
AI 代码解读

如果要从一个设备(例如:文件)读取,可以用这种方式:

QHttpPart imagePart;
imagePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpeg"));
imagePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"image\""));
imagePart.setRawHeader("Content-ID", "my@content.id"); // 添加任何你喜欢的 headers
QFile *file = new QFile("image.jpg");
file->open(QIODevice::ReadOnly);
imagePart.setBodyDevice(file);
AI 代码解读

注意: QHttpPart 在设置时不需要设备的所有权,所以应该在不需要的时候销毁该设备。比较好的办法是将 multipart 消息设置为设备的父对象,QHttpMultiPart 部分会有说明。

QHttpMultiPart

QHttpMultiPart 类似于一个 RFC 2046 所描述的 MIME multipart 消息,通过 HTTP 发送。

一个 multipart 消息包含任意数量的 body 部分(QHttpPart),由一个独特的 boundary 分割开来。QHttpMultiPart 的 boundary 由字符串 "boundary_.oOo._" 后面跟随机字符构造而成。并提供足够的唯一性,以确保它在每个部分内不重复。如果需要的话,boundary 仍然可以通过 setBoundary() 来设置。

例如,构造一个 multipart 消息,其包含一个文本部分,紧随其后的是一个图像部分:

QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);

QHttpPart textPart;
textPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"text\""));
textPart.setBody("my text");

QHttpPart imagePart;
imagePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpeg"));
imagePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"image\""));
QFile *file = new QFile("image.jpg");
file->open(QIODevice::ReadOnly);
imagePart.setBodyDevice(file);
file->setParent(multiPart); // 现在不能删除文件,所以用 multiPart 删除

multiPart->append(textPart);
multiPart->append(imagePart);

QUrl url("http://my.server.tld");
QNetworkRequest request(url);

QNetworkAccessManager manager;
QNetworkReply *reply = manager.post(request, multiPart);
multiPart->setParent(reply); // 用 reply 删除 multiPart
// 这里连接信号等
AI 代码解读

使用示例

比如multipart/form-data,其实就是浏览器用表单上传文件的方式。最常见的情景:发送邮件时添加附件,通常使用表单添加,也就是用 multipart/form-data 格式上传到服务器。

例如,上传一个本地的 png 格式图片:

这里写图片描述

可以看到请求内容的类型:

Content-Type: multipart/form-data; boundary="boundary_.oOo._MTA0NzE=MjcyNDY=ODk2Ng=="

其中表单类型为 multipart/form-data,boundary 是分隔符,和请求体中的分隔符内容一致。

由于上传附件不再使用原有的 HTTP 协议,所以请求体不再以 key=value 方式发送,而使用下述方式:

分隔符
字段内容1
分隔符
字段内容2

正如上图橙色区域显示方式一样。由于我们上传了一个图片,所以字段内容表示的是图片本身的字节(看上去像是乱码)。

注意:这里只是做了一个简单的演示,并没有把附件以表单的形式上传到任何服务器。如果要实际应用,可以调用一些第三方 API 进行尝试。

目录
打赏
0
0
0
0
34
分享
相关文章
Qt(C++)开发一款图片防盗用水印制作小工具
文本水印是一种常用的防盗用手段,可以将文本信息嵌入到图片、视频等文件中,用于识别和证明文件的版权归属。在数字化和网络化的时代,大量的原创作品容易被不法分子盗用或侵犯版权,因此加入文本水印成为了保护原创作品和维护知识产权的必要手段。 通常情况下,文本水印可以包含版权声明、制作者姓名、日期、网址等信息,以帮助识别文件的来源和版权归属。同时,为了增强防盗用效果,文本水印通常会采用字体、颜色、角度等多种组合方式,使得水印难以被删除或篡改,有效地降低了盗用意愿和风险。 开发人员可以使用图像处理技术和编程语言实现文本水印的功能,例如使用Qt的QPainter类进行文本绘制操作,将文本信息嵌入到图片中,
248 1
【qt】MDI多文档界面开发
【qt】MDI多文档界面开发
213 0
|
6月前
Qt开发
Qt开发
qt开发技巧与三个问题点
本文介绍了三个Qt开发中的常见问题及其解决方法,并提供了一些实用的开发技巧。
134 0
|
7月前
|
C++
C++ Qt开发:QUdpSocket网络通信组件
QUdpSocket是Qt网络编程中一个非常有用的组件,它提供了在UDP协议下进行数据发送和接收的能力。通过简单的方法和信号,可以轻松实现基于UDP的网络通信。不过,需要注意的是,UDP协议本身不保证数据的可靠传输,因此在使用QUdpSocket时,可能需要在应用层实现一些机制来保证数据的完整性和顺序,或者选择在适用的场景下使用UDP协议。
283 2
Qt开发网络嗅探器02
Qt开发网络嗅探器02
|
7月前
【qt】多窗口开发
【qt】多窗口开发
109 0