PDA

View Full Version : QNetworkRequest file upload -- please help



Runtime Technologies
12th July 2009, 23:35
Hey folks - thank you so much for your help. Most of this is pretty new to me, and I have been able to only get so far. Could someone familiar with QNetworkRequest and php please help me see where I am going astray?

Patching together several other attempts by various people I came up with this code to upload a file via POST to a php upload script. My code:

... from on_button_clicked() ...


QString bound,data,crlf;
QByteArray dataToSend;

bound="---------------------------7d935033608e2";
crlf=0x0d;
crlf+=0x0a;
data="--"+bound+crlf+"Content-Disposition: form-data; name=\"uploadedFile\";";
data+="filename=\"Contact List.csv\"";
data+=crlf+"Content-Type: text/plain"+crlf+crlf;
data+=inputFile.readAll(); // insert content of text file
data+=crlf+"--"+bound+"--"+crlf;
dataToSend.insert(0,data); // correct/needed?

// request init
QNetworkRequest request(QUrl("http://edm.localhost/uploader.php"));
// need to set headers here?
reply=manager.post(request,dataToSend); // perform post request

// connections
connect(reply,SIGNAL(uploadProgress(qint64,qint64) ),
SLOT(mySetValue(qint64,qint64)));
connect(reply,SIGNAL(finished()),SLOT(replyFinishe d())); // reply finished - close file



and my php script is:
<?php
$target_path = "";

if($_FILES['uploadedFile']['name'])
$target_path= $target_path.basename($_FILES['uploadedFile']['name']);
else
echo "no file name";
echo "<br>";

if(move_uploaded_file($_FILES['uploadedFile']['tmp_name'], $target_path))
echo "The file ".basename( $_FILES['uploadedFile']['name'])." has been uploaded";
else
echo "There was an error uploading the file, please try again!";
?>

The program seems to function, i.e. no errors or unexpected quitting and the progress bar updates through 100%, but I never receive the uploaded file in my upload directory (or elsewhere) as I do when I access this script through the following HTML form.

<form enctype="multipart/form-data" action="uploader.php" method="POST">
<input type="hidden" name="MAX_FILE_SIZE" value="100000000" />
Choose a file to upload: <input name="uploadedFile" type="file" /><br />
<input type="submit" value="Upload File" />
</form>

I'm running a QT4.5 (coding in QTCreator 4.5.2) on an UBUNTU 8.10 LAMP server. Thank you so much for any help!

wysota
13th July 2009, 10:21
Compare the contents of the request that goes out in both cases using a network sniffer.

Runtime Technologies
13th July 2009, 23:26
UPDATE:

Using WireShark I have been able to decipher that the $_FILES variable is just not being populated by the functioning of my QT application. I have read that this could potentially derive from an insufficiently high max_upload_size in php.ini, but with even the smallest file I see the same response.

Using WireShark I also "cleaned up" the data sent to the php script. I'm still confused, though, about the necessity of certain headers. The arrangement I have now appears to work from within my program, but WireShark responds with my coded php response to !$_FILES (echo "no file";) and a further "Bad Request ... Your browser sent a request that this server could not understand." in a continuation.


// file init
//inputFile.setFileName("test.csv");
inputFile.setFileName("main.cpp");
if(!inputFile.open(QFile::ReadOnly|QIODevice::Text )) {
ui->textEdit->append("File failed to open - contact system administrator.");

} else {
QString boundary,data,crlf,fileByteSize;
QByteArray dataToSend;

boundary="-----------------------------7d935033608e2";
crlf=0x0d;
crlf+=0x0a;

data=crlf+"--"+boundary+crlf; // start delimiter
data+="Content-Disposition: form-data; name=\"MAX_FILE_SIZE\";"+crlf+crlf;
data+=fileByteSize.setNum(inputFile.size()+1);
data+=crlf+"--"+boundary+crlf;
data+="Content-Disposition: form-data; name=\"username\";"+crlf+crlf+"username"+crlf; // !! effect username !!
data+=crlf+"--"+boundary+crlf;
data+="Content-Disposition: form-data; name=\"password\";"+crlf+crlf+"password"+crlf; // !! effect password !!
data+=crlf+"--"+boundary+crlf;
data+="Content-Disposition: form-data; name=\"uploadedFile\"; filename=\"ContactList.csv\";"+crlf;
data+="Content-Type: text/plain"+crlf+crlf+inputFile.readAll()+crlf;
data+="--"+boundary+"--"+crlf; // stop delimiter
dataToSend.insert(0,data); // convert to byte array for request

ui->textEdit->insertPlainText(dataToSend.data()); // update ui for my own sake

// request init
QNetworkRequest request(QUrl("http://edm.localhost/uploader.php"));
//request.setRawHeader("Content Type","text/plain");

//QString contentType="multipart/form-data; boundary=\""+boundary+"\"";
//QString host="http://edm.localhost/";

//request.setRawHeader("Host",host.toAscii());
// if (userAgentS!="") request.setRawHeader("User-Agent", userAgentS.toAscii());
// if (refererS!="") request.setRawHeader("Referer", refererS.toAscii());
//request.setHeader(QNetworkRequest::ContentTypeHead er,contentType.toAscii());
//request.setHeader(QNetworkRequest::ContentLengthHe ader,QVariant(inputFile.size()).toString());
//request.setUrl(QUrl("http://edm.localhost"));

//request.setRawHeader("Content Disposition","form-data; name=\"uploadedFile\"; filename=\"DownloadedContactList.csv\"");
//request.setRawHeader("Content Length",dataToSend);//fileByteSize.setNum(inputFile.size()));
//request.setHeader(QNetworkRequest::ContentTypeHead er,"multipart/form-data; boundary: -----------------------------7d935033608e2\n");
request.setHeader(QNetworkRequest::ContentLengthHe ader,inputFile.size());

reply=manager.post(request,dataToSend); // perform post request

// QByteArray data = reply->readAll();
// QTextStream out(&data);
// QString file = out.readAll();

ui->textEdit->append(reply->readAll());

// connections
connect(reply,SIGNAL(uploadProgress(qint64,qint64) ),SLOT(mySetValue(qint64,qint64)));
connect(reply,SIGNAL(finished()),SLOT(replyFinishe d())); // reply finished - close file


Any insight would be greatly appreciated.

Runtime Technologies
14th July 2009, 16:55
Woohoo! Got it .... for posterity sake and for those with similar difficulty, the finished code is:



QString boundary,data,crlf,fileByteSize;
QByteArray dataToSend; // byte array to be sent in POST

// data boundary declerations
crlf=0x0d;
crlf+=0x0a;
boundary="-----------------------------7d935033608e2";

data=boundary;
data+="Content-Disposition: form-data; name=\"uploadedFile\"; filename=\"ContactList.csv\";"+crlf;
data+="Content-Type: text/csv"+crlf+crlf+inputFile.readAll();
data+=boundary;
dataToSend=data.toAscii(); // convert data string to byte array for request

// request init
QNetworkRequest request(QUrl("http://edm.localhost/uploader.php"));
request.setRawHeader("Content-Type","multipart/form-data; boundary=\"-----------------------------7d935033608e2\"");
request.setHeader(QNetworkRequest::ContentLengthHe ader,dataToSend.size());
reply=manager.post(request,dataToSend); // perform POST request

// connections
connect(reply,SIGNAL(uploadProgress(qint64,qint64) ),SLOT(mySetValue(qint64,qint64)));
connect(reply,SIGNAL(finished()),SLOT(replyFinishe d())); // reply finished - close file


and for those who don't see the immediate differance, as I didn't within the request header, 'Content Type: ..." must actually be written as 'Content-Type: ...".

I spent 20 hours on a hyphen! If at first you don't succeed, try and try again, eh.

Thanks wysota ... the network sniffer was essential. Thanks QT Centre Forum.