PDA

View Full Version : QHttp Response content



ct
30th October 2009, 14:43
I am trying to login to a server and automate some manual stuff i.e. data entry and uploading files. Here is what I've encountered so far, I have successfully logged in and used QHttp:: post() to do the job. Now I am trying to upload some files, and I think I've got the multi-part file upload correct, however I don't know how to read the "response content" from the post. All I can read is the response header.

I am using HttpFox to see the post messages, when I post a file through the browser, after the post-data is sent there is "response content" which is in HTML, how do I capture that ?

ct
30th October 2009, 15:17
I would like to clarify a bit more..there is a tab in HttpFox (Firefox Add-in) that is called "Content" tab. All I want to do is capture the content that would appear in that tab everytime I do a POST, but of course through QHttp. Is it possible ?

ct
30th October 2009, 15:20
aggghh...dumb me...it's just the body of the page that is returned after the request. I must be doing something wrong in the multi-part upload. Moderators may delete this post.

ct
30th October 2009, 23:56
Ok, I've been banging my head whole night but I still can't get it right. Here is the scenario:

1. I am trying to upload a file through QHttp:: post()
2. I think I am successful since I get the 200 OK response but I don't get to the correct page after uploading, why is this ? Am I doing something different than the browser ? Please help to identify

here is the snippet of code I'm using




...

public:
QByteArray p_flie;
....

QFile *fptr = new QFile(filePath);
fptr->open(QIODevice::ReadOnly);
QByteArray bytes = fptr->readAll();

this->p_file.append(QString("-----------------------------139712626415117\r\n").toUtf8());
this->p_file.append(QString("Content-Disposition: form-data; name=\"workspace_item_id\"\r\n\r\n").toUtf8());
this->p_file.append(QString(this->working_id + "\r\n").toUtf8());
this->p_file.append(QString("-----------------------------139712626415117\r\n").toUtf8());
this->p_file.append(QString("Content-Disposition: form-data; name=\"step\"\r\n\r\n").toUtf8());
this->p_file.append(QString("3\r\n").toUtf8());
this->p_file.append(QString("-----------------------------139712626415117\r\n").toUtf8());
this->p_file.append(QString("Content-Disposition: form-data; name=\"page\"\r\n\r\n").toUtf8());
this->p_file.append(QString("1\r\n").toUtf8());
this->p_file.append(QString("-----------------------------139712626415117\r\n").toUtf8());
this->p_file.append(QString("Content-Disposition: form-data; name=\"jsp\"\r\n\r\n").toUtf8());
this->p_file.append(QString("/submit/choose-file.jsp\r\n").toUtf8());
this->p_file.append(QString("-----------------------------139712626415117\r\n").toUtf8());
this->p_file.append(QString(QString("Content-Disposition: form-data; name=\"file\"; filename=\"") + f.fileName() + QString("\"\r\n")).toUtf8());
this->p_file.append(QString("Content-Type: text/plain\r\n\r\n").toUtf8());
this->p_file.append(bytes);
this->p_file.append(QString("\r\n").toUtf8());
this->p_file.append(QString("-----------------------------139712626415117\r\n").toUtf8());
this->p_file.append(QString("Content-Disposition: form-data; name=\"workspace_item_id\"\r\n\r\n").toUtf8());
this->p_file.append(QString(this->working_id + "\r\n").toUtf8());
this->p_file.append(QString("-----------------------------139712626415117\r\n").toUtf8());
this->p_file.append(QString("Content-Disposition: form-data; name=\"step\"\r\n\r\n").toUtf8());
this->p_file.append(QString("3\r\n").toUtf8());
this->p_file.append(QString("-----------------------------139712626415117\r\n").toUtf8());
this->p_file.append(QString("Content-Disposition: form-data; name=\"page\"\r\n\r\n").toUtf8());
this->p_file.append(QString("1\r\n").toUtf8());
this->p_file.append(QString("-----------------------------139712626415117\r\n").toUtf8());
this->p_file.append(QString("Content-Disposition: form-data; name=\"jsp\"\r\n\r\n").toUtf8());
this->p_file.append(QString("/submit/choose-file.jsp\r\n").toUtf8());
this->p_file.append(QString("-----------------------------139712626415117\r\n").toUtf8());
this->p_file.append(QString("Content-Disposition: form-data; name=\"submit_upload\"\r\n\r\n").toUtf8());
this->p_file.append(QString("Next >\r\n").toUtf8());
this->p_file.append(QString("-----------------------------139712626415117--\r\n").toUtf8());

httpPostFile("path to submit",this->p_file);

...
void AutoPost::httpPostFile(QString path,QByteArray postMsg)
{
QHttpRequestHeader header("POST",path);
header.setContentType("multipart/form-data; boundary=-----------------------------139712626415117");
header.setValue("Host", "localhost:8080");
header.setValue("User-Agent","Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3");
header.setValue("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
header.setValue("Accept-Language","en-us,en;q=0.5");
header.setValue("Accept-Encoding","gzip,deflate");
header.setValue("Accept-Charset","ISO-8859-1,utf-8;q=0.7,*;q=0.7");
header.setValue("Keep-Alive","300");
header.setValue("Connection","keep-alive");
header.setValue("Cookie", cookie);
header.setValue("Referer","http://localhost:8080/jspui/submit");
header.setContentLength(postMsg.size());


httpPostID = http->request(header,postMsg);


}

...
//and I am reading the response like this
connect(http, SIGNAL(requestFinished(int, bool)),
this, SLOT(httpRequestFinished(int, bool)));
...
void AutoPost::httpRequestFinished(int requestID, bool error)
{
if(httpPostID == requestID)
{
QByteArray byte = http->readAll();
}
}



Is there something missing in the way file upload works ? if I get a 200 OK doesn't that mean everything should be fine :( ? In what ways could this way be different from how the browser is doing the thing ? I've captured all the headers and I couldn't figure it out.

ct
31st October 2009, 06:02
Here are the headers from browser and my application

Browser packets


Header:

POST /jspui/submit HTTP/1.1
Host localhost:8080
User-Agent Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.4) Gecko/20091016 Firefox/3.5.4
Accept text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language en-us,en;q=0.5
Accept-Encoding gzip,deflate
Accept-Charset ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive 300
Connection keep-alive
Referer http://localhost:8080/jspui/submit
Cookie JSESSIONID=696FF5F9F3FFE011DCD4662AEAC0BCF8
Content-Type multipart/form-data; boundary=---------------------------210982431416320
Content-Length 1161


Post-Data

-----------------------------210982431416320
Content-Disposition: form-data; name="workspace_item_id"

193
-----------------------------210982431416320
Content-Disposition: form-data; name="step"

3
-----------------------------210982431416320
Content-Disposition: form-data; name="page"

1
-----------------------------210982431416320
Content-Disposition: form-data; name="jsp"

/submit/choose-file.jsp
-----------------------------210982431416320
Content-Disposition: form-data; name="file"; filename="essay.txt"
Content-Type: text/plain

This is a test file.
-----------------------------210982431416320
Content-Disposition: form-data; name="workspace_item_id"

193
-----------------------------210982431416320
Content-Disposition: form-data; name="step"

3
-----------------------------210982431416320
Content-Disposition: form-data; name="page"

1
-----------------------------210982431416320
Content-Disposition: form-data; name="jsp"

/submit/choose-file.jsp
-----------------------------210982431416320
Content-Disposition: form-data; name="submit_upload"

Next >
-----------------------------210982431416320--



My Application


Header

POST /jspui/submit HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: http://localhost:8080/jspui/submit
Cookie: JSESSIONID=07B22972405E63E712CC957FEDC28647
content-type: multipart/form-data; boundary=--AaB03x
content-length: 765

Post data

--AaB03x
Content-Disposition: form-data; name="workspace_item_id"

194
--AaB03x
Content-Disposition: form-data; name="step"

3
--AaB03x
Content-Disposition: form-data; name="page"

1
--AaB03x
Content-Disposition: form-data; name="jsp"

/submit/choose-file.jsp
--AaB03x
Content-Disposition: form-data; name="file"; filename="essay.txt"
Content-Type: text/plain

This is a test file.
--AaB03x
Content-Disposition: form-data; name="workspace_item_id"

194
--AaB03x
Content-Disposition: form-data; name="step"

3
--AaB03x
Content-Disposition: form-data; name="page"

1
--AaB03x
Content-Disposition: form-data; name="jsp"

/submit/choose-file.jsp
--AaB03x
Content-Disposition: form-data; name="submit_upload"

Next >
--AaB03x--

ct
1st November 2009, 01:59
Ok, after banging my head for another day, I still can't figure out if I am doing anything wrong. I realized that I am using Qt 4.5.2 so it could very well be a bug.

In Qt 4.5.3 change log I see this



QNetworkAccessManager
* [256240] Proper handling of HTTP redirect in AlwaysCache mode.
* [257662] Fix timing issues that could trigger double sending of an
HTTP request.


Please suggest if these bugs were related to QHttp too ? Should I use QNetworkAccessManager instead with the latest version 4.5.3 ?

mgoetz
2nd November 2009, 11:59
Please suggest if these bugs were related to QHttp too ?

they were not.


Should I use QNetworkAccessManager instead with the latest version 4.5.3 ?

yes :) QHttp is deprecated with the soon to be released Qt 4.6.

ct
3rd November 2009, 02:49
I used curl and now everything is fine. This is how curl sent it's header



Curl trace file:

=> Send header, 322 bytes (0x142)
0000: POST /jspui/submit HTTP/1.1
001d: User-Agent: curl/7.19.5 (i586-pc-mingw32msvc) libcurl/7.19.5 zli
005d: b/1.2.3
0066: Host: localhost:8080
007c: Accept: */*
0089: Cookie: JSESSIONID=C03B80796C0718E4CB5CA174422DD9FB
00be: Content-Length: 1139
00d4: Expect: 100-continue
00ea: Content-Type: multipart/form-data; boundary=--------------------
012a: --------13c11370a722
0140:
<= Recv header, 23 bytes (0x17)
0000: HTTP/1.1 100 Continue
=> Send data, 551 bytes (0x227)
0000: ------------------------------13c11370a722
002c: Content-Disposition: form-data; name="workspace_item_id"
0066:
0068: 421
006d: ------------------------------13c11370a722
0099: Content-Disposition: form-data; name="step"
00c6:
00c8: 3
00cb: ------------------------------13c11370a722
00f7: Content-Disposition: form-data; name="page"
0124:
0126: 1
0129: ------------------------------13c11370a722
0155: Content-Disposition: form-data; name="jsp"
0181:
0183: /submit/choose-file.jsp
019c: ------------------------------13c11370a722
01c8: Content-Disposition: form-data; name="file"; filename="essay.txt
0208: "
020b: Content-Type: text/plain
0225:
=> Send data, 20 bytes (0x14)
0000: This is a test file.
=> Send data, 568 bytes (0x238)
0000:
0002: ------------------------------13c11370a722
002e: Content-Disposition: form-data; name="workspace_item_id"
0068:
006a: 421
006f: ------------------------------13c11370a722
009b: Content-Disposition: form-data; name="step"
00c8:
00ca: 3
00cd: ------------------------------13c11370a722
00f9: Content-Disposition: form-data; name="page"
0126:
0128: 1
012b: ------------------------------13c11370a722
0157: Content-Disposition: form-data; name="jsp"
0183:
0185: /submit/choose-file.jsp
019e: ------------------------------13c11370a722
01ca: Content-Disposition: form-data; name="submit_upload"
0200:
0202: Next >
020a: ------------------------------13c11370a722--
<= Recv header, 17 bytes (0x11)
0000: HTTP/1.1 200 OK
<= Recv header, 27 bytes (0x1b)
0000: Server: Apache-Coyote/1.1
<= Recv header, 40 bytes (0x28)
0000: expires: Thu, 01 Jan 1970 00:00:00 GMT
<= Recv header, 18 bytes (0x12)
0000: Pragma: no-cache
<= Recv header, 25 bytes (0x19)
0000: Cache-control: no-store
<= Recv header, 39 bytes (0x27)
0000: Content-Type: text/html;charset=UTF-8
<= Recv header, 22 bytes (0x16)
0000: Content-Language: en
<= Recv header, 28 bytes (0x1c)
0000: Transfer-Encoding: chunked
<= Recv header, 37 bytes (0x25)
0000: Date: Tue, 03 Nov 2009 16:41:43 GMT
<= Recv header, 2 bytes (0x2)
0000:



For QHttp too I did receive 200 OK response..but the file was not uploaded. What is it that curl is doing different so that the file gets uploaded ?

ct
3rd November 2009, 02:51
The only difference I see is Expect: , could it be this ?

radory
11th July 2010, 11:06
After refering your code, I made some modifies, i noticed that the boundary must encode with ASCII, it works for me now....i am still wondering when i will need to delete the reply2(QNetworkReply *reply2)....i am not sure if it cause memory leaking or not....
sorry for my poor English, I'm a Chinese.....


#include <QtGui>
#include <QtNetwork/QNetworkAccessManager>
#include <QUrl>
#include <QtNetwork/QNetworkRequest>
#include <QtNetwork/QNetworkReply>

static QNetworkReply *reply;

class TOOTLabel : public QLabel
{
Q_OBJECT
public:
TOOTLabel(QWidget *parent =0) : QLabel(parent) {
uploadBtn = new QPushButton("uplaod....");
connect(uploadBtn, SIGNAL(clicked()), this, SLOT(uploadFile()));

uploadBtn->show();
uploadBtn->resize(240,100);
}

~TOOTLabel()
{
delete reply2;
}

public slots:
void TOOTReadyRead()
{
QImage img ;
img.load(reply, "JPEG");
setPixmap(QPixmap::fromImage(img));
show();
resize(img.width(),img.height());
}

void uploadFile()
{
QStringList fileList = QFileDialog::getOpenFileNames(
this,tr("Select some files to upload....")
,QDir::currentPath());

if(fileList.count() < 1) return;

manager2 = new QNetworkAccessManager;
// QString fileName = "tootzoe.jpg";
QString newPathName = "newtootzoe.jpg";

// foreach(QString fileName, fileList){
QString fileName = fileList.at(0);
file = new QFile(fileName);
if(!file->open(QFile::ReadOnly )) { qDebug() << "Error opening file....";return ;}

////================================================== =
QByteArray formData;
QString _boundary = "-----------------------------7d6bb34502ce";
QString contenttype = "multipart/form-data; boundary=" + _boundary;

formData.append(QString("--" + _boundary + "\r\n").toAscii());
//
formData.append(QString("Content-Disposition: form-data; name=\"Filename\"\r\n\r\n").toUtf8());
formData.append(QString(fileName +"\r\n").toUtf8());
formData.append(QString("--" + _boundary + "\r\n").toAscii()); // ASCII encoder
//////////
formData.append(QString("Content-Disposition: form-data; name=\"RelPathName\"\r\n\r\n").toUtf8());
formData.append(QString(newPathName +"\r\n").toUtf8());
formData.append(QString("--" + _boundary + "\r\n").toAscii()); // ASCII encoder
//////////
formData.append(QString("Content-Disposition: form-data; name=\"sqlQuery\"\r\n\r\n").toUtf8());
formData.append(QString("FlashSentFileData\r\n").toUtf8());
formData.append(QString("--" + _boundary + "\r\n").toAscii()); // ASCII encoder
//数据块 begin
formData.append(QString("Content-Disposition: form-data; name=\"Filedata\"; filename=\"" + fileName + "\"\r\n").toUtf8());
formData.append(QString("Content-Type: application/octet-stream\r\n\r\n").toUtf8());
formData.append( file->readAll());
formData.append(QString("\r\n").toAscii());
//数据块 end
formData.append(QString("--" + _boundary + "--\r\n").toAscii());


QNetworkRequest request2(QUrl("http://localhost/console/uploadfile.aspx")) ;
request2.setHeader(QNetworkRequest::ContentTypeHea der, contenttype);
request2.setHeader(QNetworkRequest::ContentLengthH eader, formData.size());
reply2 = manager2->post(request2, formData);
connect(reply2, SIGNAL(finished()), this,SLOT(uploadFileFinished()));
qDebug() << "uploading " << fileName;

// }
file->close();

}

void uploadFileFinished()
{
qDebug() << "finished upload.... " << reply2->attribute(QNetworkRequest::HttpStatusCodeAttribute ).toInt() ;
qDebug() << QString( reply2->readAll() );
}


private:
QPushButton *uploadBtn;
QNetworkAccessManager *manager2;
QNetworkReply *reply2;
QFile *file;

};

int main(int argc, char **argv)
{
QApplication app(argc, argv);

QNetworkAccessManager manager;
QNetworkRequest request;
request.setUrl(QUrl("http://www.google.com/intl/en_ALL/images/logo2.gif"));

reply = manager.get(request);
TOOTLabel imgLabel;
QObject::connect( reply, SIGNAL(finished()), &imgLabel, SLOT(TOOTReadyRead()));

imgLabel.show();

return app.exec();
}

#include "main.moc"