如何使用QNetworkAccessManager将数据POST到URL

62

我有一个Web服务,需要使用Qt将一些数据POST到该服务。

我想到可以在向Web服务POST时使用QByteArray。

我的问题是,我该如何格式化这个数组,以便在另一端能够正确解析?

到目前为止,这是我拥有的代码:

    // Setup the webservice url
    QUrl serviceUrl = QUrl("http://myserver/myservice.asmx");
    QByteArray postData;

   /* 
   Setup the post data somehow
   I want to transmit:
   param1=string,
   param2=string
   */

    // Call the webservice
    QNetworkAccessManager *networkManager = new QNetworkAccessManager(this);
    connect(networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(serviceRequestFinished(QNetworkReply*)));
    networkManager->post(QNetworkRequest(serviceUrl), postData);

谢谢!

6个回答

136

由于一些参数和值可能需要进行 UTF-8 编码和百分号编码(空格、&、=、特殊字符等),因此您应该使用 QUrl(适用于 Qt 4)或 QUrlQuery(适用于 Qt 5)来构建发布的字符串。

Qt 4 的示例代码:

QUrl postData;
postData.addQueryItem("param1", "string");
postData.addQueryItem("param2", "string");
...
QNetworkRequest request(serviceUrl);    
request.setHeader(QNetworkRequest::ContentTypeHeader, 
    "application/x-www-form-urlencoded");
networkManager->post(request, postData.encodedQuery());

对于 Qt 5

QUrlQuery postData;
postData.addQueryItem("param1", "string");
postData.addQueryItem("param2", "string");
...
QNetworkRequest request(serviceUrl);
request.setHeader(QNetworkRequest::ContentTypeHeader, 
    "application/x-www-form-urlencoded");
networkManager->post(request, postData.toString(QUrl::FullyEncoded).toUtf8());

从Qt 4.8开始,如果您需要上传文件,也可以使用QHttpMultiPart


7
这绝对是完成所需任务的最合适方式。+1. - Joshua Burns
2
从Qt 5开始,QUrl不再具有addQueryItem()方法。 - mjk99
1
@mjk99 QUrlQuery 有这个功能,但它没有 .encodedQuery() - JVE999
请注意,在Qt 4.8中,addQueryItem()方法不会像HTML表单一样将空格(ASCII 0x20)编码为加号(+)。详见:http://doc.qt.io/qt-4.8/qurl.html#addQueryItem - djvg
1
我更喜欢使用 postData.query().toUtf8() - Tomilov Anatoliy

20

我使用了:

QByteArray postData;
postData.append("param1=string&");
postData.append("param2=string");

因此,每个参数之间不是换行符。


11
这种方法不能保护输入中包含的"&"字符。如果“string”是用户输入的,他们可能会注入参数。 - Halfgaar

9

将alexisdm的答案更新为Qt5:

// Setup the webservice url
QUrl serviceUrl = QUrl("http://your.url");
QByteArray postData;

QUrlQuery query;
query.addQueryItem("param1","string1");
query.addQueryItem("param2","string2");

postData = query.toString(QUrl::FullyEncoded).toUtf8();

// Call the webservice
QNetworkAccessManager *networkManager = new QNetworkAccessManager(this);
connect(networkManager, SIGNAL(finished(QNetworkReply*)),
        SLOT(onPostAnswer(QNetworkReply*)));

QNetworkRequest networkRequest(serviceUrl);
networkRequest.setHeader(QNetworkRequest::ContentTypeHeader,"application/x-www-form-urlencoded");

networkManager->post(networkRequest,postData);

不要忘记包含。
QT += network

in .pro.


2
这段代码与仅构造QByteArray的Juha不同之处在于,postData是"?param1=string1&param2=string2",这会出错。 - Halfgaar
3
如果您正在使用相同的网络访问管理器进行多个请求,那么将槽连接到QNetworkReplyfinished()信号而不是QNetworkAccessManager是有道理的。这样,您可以为每个请求拥有不同的信号并单独处理它们,或者使用readyRead()信号逐部分处理数据。 - nurettin

6
实际答案是:
QByteArray postData;
postData.append("param1=string&");
postData.append("param2=string");

注意:这里要使用"&"!!!.

我没有注意到Juha在这里的回答,浪费了很多时间用",\n"方法测试我的代码。

请将正确答案更改为Juha的。


3

这里有另一种处理方式,我也使用了您的代码来提供完整的代码:

     // Setup the webservice url         
     QUrl serviceUrl = QUrl("http://myserver/myservice.asmx");
     QByteArray postData;

     QUrl params;
     params.addQueryItem("param1","string1");
     params.addQueryItem("param2","string2");

     postData = params.encodedQuery();

     // Call the webservice
     QNetworkAccessManager *networkManager = new QNetworkAccessManager(this);
     connect(networkManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(serviceRequestFinished(QNetworkReply*)));

      networkManager->post(QNetworkRequest(serviceUrl), postData);

-4
QByteArray postData;
postData.append("param1=string,\n");
postData.append("param2=string\n");

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接