PDA

View Full Version : Upload file to HTTP server



produktdotestow
17th April 2011, 15:11
Hi.
I'm trying to write class for uploading files to HTTP server. I have a one, which uses QNetworkAccessManager::post(const QNetworkRequest & request, const QByteArray & data) method, but all the time when i want to upload file - i have to load entire(!) of file content into memory (QByteArray). I decided to find a better way to do the same. I stumbled on this project:
http://code.google.com/p/datacod-qt-tools/

and in uploader.cpp file
(http://code.google.com/p/datacod-qt-tools/source/browse/trunk/upcoder/uploader.cpp, from line no. 85)

i found that i can do it better by creating class that inherits QIODevice and reimplementing virtual qint64 readData(char *data, qint64 maxlen) and virtual qint64 size() methods. When you want to upload file - just create instance of this class and pass it to QNetworkAccessManager::post(const QNetworkRequest & request, QIODevice * data) method. Here's prepared class:
http://code.google.com/p/datacod-qt-tools/source/browse/trunk/upcoder/qupfile.cpp

It seems to be a good solution and i thought that it'll work. Unfortunately - it doesn't. QUpFile::readData(char *data, qint64 maxlen) is not called even once and uploadProgress(qint64 bytesWritten, qint64 bytesTotal) signal is emitted only one time (bytesWritten = bytesTotal = 0).

Anybody have idea what's wrong with it or have another way to upload file without loading entire of its content into memory?

Thank you in advance.
Greet.

produktdotestow
19th April 2011, 20:24
Solved. If somebody needs help with similar problem - just write here :)

kosasker
25th May 2011, 14:03
I need a simple solution about this... I Keeping search too.
Regards.
Kos Asker.

kosasker
27th May 2011, 15:16
Here is a complete code about this thread. There is no authentication progress with this code.




void MainWindow::sendfile()
{

QFile file("licensefile"); //lets get the file by filename
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) //accessibility controll for file
{
qDebug() << "file open failure"; //send message if file cant open
}
QByteArray line; //a qbytearray object for read file line by line
while (!file.atEnd())
{
line.append(file.readLine());
}
//we read file line by line with no error handling for reading time!!

file.close();
QByteArray boundary; //actually i cant understand that why we are using a second byte array for file sending.
// if someone know this trick please write below. I write this code like the other examples.

QByteArray datas(QString("--" + boundary + "\r\n").toAscii());
datas += "Content-Disposition: form-data; name=\"file\"; filename=\""+file.fileName()+"\"\r\n";
//here is the http header for manuplate a normal http form and form file object

datas += "Content-Type: image/jpeg\r\n\r\n"; //file type is here
datas += line; //and our file is giving to form object
datas += "\r\n";
datas += QString("--" + boundary + "\r\n\r\n").toAscii();
datas += "Content-Disposition: form-data; name=\"upload\"\r\n\r\n";
datas += "Uploader\r\n";
datas += QString("--" + boundary + "--\r\n").toAscii();

QNetworkRequest req;
req.setUrl(QUrl("http://192.168.0.167/input.php")); //my virtual servers' ip address and tiny php page url is here
req.setRawHeader("Content-Type", "multipart/form-data; boundary=" + boundary); // we must set the first header like this. its tell the server, current object is a form

QNetworkAccessManager *manager = new QNetworkAccessManager; //using qnetwork access manager for post data

connect(manager,SIGNAL(finished(QNetworkReply*)),t his,SLOT(erroron_filesend(QNetworkReply*))); //connecting manager object for errors here
manager->post(req,datas); //send all data

}

void MainWindow::erroron_filesend(QNetworkReply *replye)
{
if (replye->error() !=0)
{
QMessageBox::information(this,"Connection Error",replye->errorString());
return;
}
else
{
QString message_d = QString("Upload Complete");
QMessageBox::information(this, "Upload Complete", message_d);
return;
}
}


Php Code


<?php
$filename = $_FILES['file']['name'];
$source = $_FILES['file']['tmp_name'];
$target = 'upload/'.$filename;
move_uploaded_file($source, $target)
?>


Its a very simple code and dont try to upload big files (up to 1 Mbyte) with this code.
This one is very dirty i know. Its will be helpfull, i wish... Sorry for bad English. Regards.

hugocongtu
27th July 2011, 05:33
Hi produktdotestow,

I'm quite interested in your project http://code.google.com/p/datacod-qt-tools/ because I'm currently developing an upload manager with Qt and using .NET web service at the server side. I read your code but I realized that you use a form at the server side. So in my case, how can pass parameters (username and password) and QUpFile to web service.

thank you very much!
Trung

produktdotestow
30th July 2011, 14:18
This
http://code.google.com/p/datacod-qt-tools/
is not my project, but it's not important.

As i understood you want to upload file and pass username and password to server, yes?

1. Get working QUpFile class
2. Create instance
3. Set head and tail using setHead and setTail methods

upfile->setHead("------------hKdQAaQIL4zeExpbXAmwlW\r\nContent-Disposition: form-data; name=\"username\"\r\n\r\nusername\r\n------------hKdQAaQIL4zeExpbXAmwlW\r\nContent-Disposition: form-data; name=\"password\"\r\n\r\npassword\r\n------------hKdQAaQIL4zeExpbXAmwlW\r\nContent-Disposition: form-data; name=\"file\"; filename=\"yourFileName\"\r\nContent-Type: application/octet\r\n\r\n");
upfile->setTail("\r\n------------hKdQAaQIL4zeExpbXAmwlW--");
4. Create QNetworkRequest object and set Content-Type header like that:

request.setHeader(QNetworkRequest::ContentTypeHead er, "multipart/form-data; boundary=----------hKdQAaQIL4zeExpbXAmwlW");
5. Use
QNetworkReply* QNetworkAccessManager::post(const QNetworkRequest &request, QIODevice *data) to post your request to server:

QNetworkReply *reply = networkAccessManager->post(request, upfile);