在测试新浪微博REST API时,有些API接口规定:请求必须用POST方式提交,并且注意采用multipart/form-data编码方式;

于是使用了下面的代码进行提交:

QString strUrl = QStringLiteral("https://api.weibo.com/2/statuses/upload.json");
QUrl url(strUrl);

QNetworkRequest request(url);
request.setHeader(QNetworkRequest::ContentTypeHeader, "multipart/form-data");
QUrlQuery postData;
postData.addQueryItem("access_token", access_token);
postData.addQueryItem("status", "string");

QNetworkAccessManager* networkManager = new QNetworkAccessManager(this);
networkManager->post(request, postData.toString(QUrl::FullyEncoded).toUtf8());

但是这种方法报找不到参数的错误,说明这种方法不适用新浪微博API,于是使用Postman做了一个正确的POST请求,然后解析Postman发送的HTTP Body,抓取到的Body数据如下:

------WebKitFormBoundaryN1KAV8VHBSGaroV3\r\nContent-Disposition: form-data; name="access_token"\r\n\r\nthis is access_token\r\n------WebKitFormBoundaryN1KAV8VHBSGaroV3\r\nContent-Disposition: form-data; name="status"\r\n\r\nstring\r\n------WebKitFormBoundaryN1KAV8VHBSGaroV3--\r\n

通过分析HTTP Body,找到了下面的方法:

QString strUrl = QStringLiteral("https://api.weibo.com/2/statuses/upload.json");
QUrl url(strUrl);
QNetworkRequest request(url);

// request.setHeader(QNetworkRequest::ContentTypeHeader, "multipart/form-data");  // 不要加这句代码。加了这句虽然Body格式是正确的但是还是识别不了参数。
    
QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);

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

QHttpPart authPart;
authPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"access_token\""));
authPart.setBody(access_token.toUtf8());

// 上传图片文件
//QMimeType mime = db.mimeTypeForFile(absoluteFilePath);
QHttpPart imagePart;
imagePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"pic\"; filename=\"bug.jpg\""));
imagePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpeg"));
QFile *file = new QFile("C:/Users/Administrator/Desktop/bug.jpg");
file->open(QIODevice::ReadOnly);
imagePart.setBodyDevice(file);
file->setParent(multiPart); // we cannot delete the file now, so delete it with the multiPart

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

QNetworkReply* reply = networkManager->post(request, multiPart);
multiPart->setParent(reply); // delete the multiPart with the reply

使用上面的方法,成功发布了一条微博并上传了一个图片。

这里需要注意的是,由于文档中提到了“采用multipart/form-data编码方式”,所以就加了下面的代码,但是加了这段代码反而识别不了:

request.setHeader(QNetworkRequest::ContentTypeHeader, "multipart/form-data");  

通过抓包发现了问题,如果“Content-Type”的值为 multipart/form-data ,则需要在“Content-Type”加入“boundary”:

Content-Type: multipart/form-data; boundary="boundary.oOo.MTQzMjg=MjgzNDM=OTQ1Ng=="

标签: Qt, http, QNetworkAccessManager, POST, REST API

添加新评论