1. 程式人生 > >關於QThttp post上傳混合表單資料例項總結

關於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屬性,否則真的很無奈。