Qt之QHttpMultiPart(微信小程序云服务器上传文件)

简介

网页的form表单中,如果存在上传文件的表单,则需要将form标签设置enctype="multipart/form-data"属性,意思是将Content-Type设置成multipart/form-data,multipart 类型对发送非文本类型非常有用。Qt中对应为QHttpMultiPart、QHttpPart,QHttpMultiPart 类似于一个 RFC 2046 所描述的 MIME multipart 消息,通过 HTTP 发送,常用于传输较大的文件数据。

enum QHttpMultiPart::ContentType

Constant 常数 Value 价值 Description 描述
QHttpMultiPart::MixedType 0 对应于"multipart/mixed"子类型,意味着主体部件彼此独立,如RFC 2046中所述。
QHttpMultiPart::RelatedType 1 对应于"multipart/related"子类型,意味着主体部件彼此相关,如RFC 2387中所述。
QHttpMultiPart::FormDataType 2 对应于“multipart/form-data”子类型,这意味着主体部分包含表单元素,如RFC 2388中所述。
QHttpMultiPart::AlternativeType 3 对应于"multipart/alternative"子类型,这意味着主体部分是相同信息的可选表示,如RFC 2046中所述。

下面我们看下微信小程序云服务器中关于上传文件的规定:

上传链接使用说明

用户获取到返回数据后,需拼装一个 HTTP POST 请求,其中 url 为返回包的 url 字段,Body 部分格式为 multipart/form-data,具体内容如下:

key value 说明
key this/is/a/example/file.path 请求包中的 path 字段
Signature q-sign-algorithm=sha1&q-ak=AKID9... 返回数据的 authorization 字段
x-cos-security-token Cukha70zkXIBqkh1Oh... 返回数据的 token 字段
x-cos-meta-fileid HDze32/qZENCwWi5... 返回数据的 cos_file_id 字段
file 文件内容 文件的二进制内容

其中HttpPart部分的key、Signature、x-cos-security-token、x-cos-meta-fileid均由请求地址返回数据获得。:

POST https://api.weixin.qq.com/tcb/uploadfile?access_token=ACCESS_TOKEN

知道了上传文件的方法,现在我们开始撸起袖子加油干吧!

此处重点说明下:

文档中说我们不需要指定boundary,它也是会自动给你添加boundary的,前提是必须保持MIME中的boundary和请求头里的boundary值一致,因此需要添加请求头中的boundary,否则传不了,如果自定义boundary,也需要和请求头中的保持一致!(官方文档中的说法存在一定的问题)

QNetworkRequest mulRequest;
mulRequest.setHeader(QNetworkRequest::ContentTypeHeader,"multipart/form-data;boundary=boundary_.oOo._");

上传的表单中的Body部分,使用QHttpPart对每个需要上传的字段进行设置,QHttpPart 类拥有一个 body 部位,用于 HTTP multipart MIME消息中(由 QHttpMultiPart 表示)。一个 QHttpPart 由一个 header 块和数据块组成,彼此之间存在两个连续换行。要设置 headers,使用 setHeader() 和 setRawHeader(),对于读取小数据块,使用 setBody();如果是更大数据块,例如:图像,使用 setBodyDevice()。下面看看上传文件名为“3.png”的图片至小程序云服务器的代码段:

void JsonDataModel::sendFileData(QString path,QString url,QString authorization,QString token,QString cos_file_id){//此处为获取到的body数据,待上传用
    QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
    QNetworkRequest mulRequest;
    mulRequest.setHeader(QNetworkRequest::ContentTypeHeader,"multipart/form-data;boundary=boundary_.oOo._");//此处boundary不能省!需要和QHttpMultiPart中的一致

    QString fileName = QFileDialog::getOpenFileName(0,
                       tr("选择图片"),QDir::currentPath(), tr("Image Files (*.png *.jpg *.bmp)"));//选择3.png的路径
    QFile *file = new QFile(fileName,multiPart);//开辟新的储存空间给文件,当释放multiPart空间时同时释放文件空间
    file->open(QIODevice::ReadOnly);

    QHttpPart keyPart;
    keyPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"key\""));
    keyPart.setBody(path.toLatin1());

    QHttpPart authorizationPart;
    authorizationPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"Signature\""));
    authorizationPart.setBody(authorization.toLatin1());

    QHttpPart tokenPart;
    tokenPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"x-cos-security-token\""));
    tokenPart.setBody(token.toLatin1());

    QHttpPart filePart;
    filePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"x-cos-meta-fileid\""));
    filePart.setBody(cos_file_id.toLatin1());

    QHttpPart imagePart;
    imagePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/png"));
    imagePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data;name=\"file\""));
//    imagePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data;name=\"file\";filename=\"3.png\"")); 部分服务器可能需要添加filename字段,小程序云服务器不需要此字段   
    imagePart.setBodyDevice(file);

    multiPart->append(keyPart);
    multiPart->append(authorizationPart);
    multiPart->append(tokenPart);
    multiPart->append(filePart);
    multiPart->append(imagePart);

    QUrl u(url);
    mulRequest.setUrl(u);
    QNetworkReply *r = manager->post(mulRequest, multiPart);
    connect(r,SIGNAL(finished()),this,SLOT(slotSendFileData()));
    multiPart->setParent(r); // delete the multiPart with the reply防止内存泄漏,在槽函数中释放

}

上传后图片在小程序云开发控制台中查看:

发布了8 篇原创文章 · 获赞 14 · 访问量 2283

猜你喜欢

转载自blog.csdn.net/zjgo007/article/details/105006140
今日推荐