关于QThttp post上传混合表单数据实例总结
最近使用QT做一个应用,需要使用一下几个库模拟http表单上传。走了很多弯路,经过很多次实验抓包之后,终于可以上传成功了。
#include "QNetworkAccessManager"
#include "QUrl"
#include "QHttpMultiPart"
#include "QNetworkRequest"
qt 官网给出了一些例子,上传文本的时候可以成功,但是等到长传图片的时候就有了一些问题,通过抓包分析:
1.单纯上传文本文档时候
抓包如下:正常上传
------WebKitFormBoundaryMpB6TGuCBoHAKJej
Content-Disposition: form-data; name="tokenid"
001001
------WebKitFormBoundaryMpB6TGuCBoHAKJej
Content-Disposition: form-data; name="mid"
001
>------WebKitFormBoundaryMpB6TGuCBoHAKJej--
上传图片的时候:
------WebKitFormBoundaryMpB6TGuCBoHAKJej
Content-Disposition: form-data; name="tokenid"
001001
------WebKitFormBoundaryMpB6TGuCBoHAKJej
Content-Disposition: form-data; name="mid"
001
------WebKitFormBoundaryMpB6TGuCBoHAKJej--
Content-Disposition: form-data; name="pic"
asdfhsdfndfhwqdjddau7&&(此处乱码,为二进制或者是base64?)
------WebKitFormBoundaryMpB6TGuCBoHAKJej--
经过反复抓取网页向服务器的请求取数据,发现了一个问题,就是qt官方给的历程上少了一个Content-Disposition属性,导致服务器无法识别。
更改后的程序查抓包后如下:
------WebKitFormBoundaryMpB6TGuCBoHAKJej
Content-Disposition: form-data; name="tokenid"
001001
------WebKitFormBoundaryMpB6TGuCBoHAKJej
Content-Disposition: form-data; name="mid"
001
------WebKitFormBoundaryMpB6TGuCBoHAKJej--
Content-Disposition: form-data; name="pic";filename="hello.jpg"
asdfhsdfndfhwqdjddau7&&(此处乱码,为二进制或者是base64?)
------WebKitFormBoundaryMpB6TGuCBoHAKJej--
ok,到此数据上传成功。一下为部分代码,可实现上传图片和文本信息到服务器:
代码:
void Controler::upDatasToCloud()
{
QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
/* tokenid */
QHttpPart textPart; textPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"tokenid\""));
textPart.setBody("001001");
multiPart->append(textPart);
/* mid */
textPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"mid\""));
textPart.setBody(this->ui.lineEdit_no->text().toUtf8());
multiPart->append(textPart);
QHttpPart imagePart;
imagePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpeg"));
imagePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"pic1\"; filename=\""+path_face+"\""));
QFile *file = new QFile(path_face);
file->open(QIODevice::ReadOnly);
imagePart.setBodyDevice(file);
//file->setParent(multiPart); // we cannot delete the file now, so delete it with the multiPart
multiPart->append(imagePart);
QHttpPart imagePart1;
imagePart1.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/png"));
imagePart1.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"pic2\"; filename=\""+path_shetai+"\""));
QFile *file1 = new QFile(path_shetai);
file1->open(QIODevice::ReadOnly);
imagePart1.setBodyDevice(file1);
//file1->setParent(multiPart);
multiPart->append(imagePart1);
QUrl url("http:your post url");
QNetworkRequest *request=new QNetworkRequest(url);
QNetworkAccessManager *manager =new QNetworkAccessManager();
QNetworkReply *reply = manager->post(*request, multiPart);
multiPart->setParent(reply); // delete the multiPart with the reply
// here connect signals etc.
//更新上传进度
QObject::connect(reply, &QNetworkReply::uploadProgress, [this](int a, int b) {
this->ui.label_add->setText(QString::number(((float)a) / b));
});
QObject::connect(reply, &QNetworkReply::readyRead, [=]() {
qDebug() << "rpy:"<< reply->errorString() << reply->readAll();
//文件关闭很多种,但是切记不能提前关闭,否则上传进度卡死。
file->close();
file1->close();
});
}
这个函数就可以实现混合数据表单上传了,切记加入filename属性,否则真的很无奈。