Issue in Uploading Image file using post method:
-
Hello All,
I am trying to upload an image file on the postman echo server using the post method. I can do it successfully using the postman application, as shown below.
When I try to implement the functionality using Qt, I do not get any response from the server.
Get request functionality work fine without any error, but there is no response for the post method please refer the below code:QUrl testUrl("https://postman-echo.com/post"); QFile file("upload.jpeg"); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { qDebug() << "file open failure"; //send message if file cant open } file.close(); QByteArray boundary; QByteArray datas(QString("--" + boundary + "\r\n").toUtf8()); datas += "Content-Disposition: form-data; name=\"file\"; filename=\"" + file.fileName() + "\"\r\n"; datas += "Content-Type: image/jpeg\r\n\r\n"; //file type is here datas += "\r\n"; datas += QString("--" + boundary + "\r\n\r\n").toUtf8(); datas += "Content-Disposition: form-data; name=\"upload\"\r\n\r\n"; datas += "Uploader\r\n"; datas += QString("--" + boundary + "--\r\n").toUtf8(); _request.setUrl(testUrl); request.setRawHeader("Content-Type", "multipart/form-data; boundary=" + boundary); _manager->post(_request, datas); //send all data
Reference:
https://doc.qt.io/archives/qt-4.8/qhttpmultipart.html
https://www.qtcentre.org/threads/40734-Upload-file-to-HTTP-server -
@JonB : Currently I am using the following :
QObject::connect(_manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(managerFinished(QNetworkReply*)));
But the signal is not being triggered i have put breakpoint in my slot it is not being invoked
Can you please try connecting to the following https://postman-echo.com/post
it up and running.
Thanks -
@JonB :
Hey, apologies for the late reply.
I analyzed the debug logs carefully and figured there was
an issue with QSslSocket, unable to resolve things. On further digging down the problem, I came to know that run time SSL libraries were missing. I downloaded the DLLs based on the build version, placed them in the .exe folder, and everything started working. -
@Kira :
Hello, everyone reopening the issue because of the related problem.
I am trying to upload a jpeg file using QHttpMultipart the program is as given below:QFile* file; foreach(QString filename, images) { //QFile file = new QFile("C:/Aeonscan/Studies/2.jpeg"); file = new QFile(filename); file->open(QIODevice::ReadOnly ); qDebug() << "File path:" << filename; QHttpMultiPart* multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType); QHttpPart imagePart; //imagePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("text/plain")); imagePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"file\"; filename=\"" + file->fileName() + "")); //QHttpPart textPart; //textPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"name\"")); //textPart.setBody("toto");/* toto is the name I give to my file in the server */ //QString apkLocation = "Test"; imagePart.setBodyDevice(file); file->setParent(multiPart); // we cannot delete the file now, so delete it with the multiPart //multiPart->append(textPart); multiPart->append(imagePart); QNetworkRequest request; request.setUrl(testUrl); //_manager->post(request, multiPart); multiPart->setParent(_manager->post(request, multiPart)); file->close();
I am getting the following error
QIODevice::read (QFile, "upload.jpeg"): device not open
QIODevice::read (QFile, "2.jpeg"): device not open
And get the following error message:
Error message: QNetworkReply::NetworkError(UnknownNetworkError)
But when I replace the following line
file = new QFile(filename);
with the following line:
QFile file = new QFile("C:/Studies/2.jpeg");
everything works fine without any error. -
@J-Hilk : Thanks a lot for reply, got it running
There were couple of issues:- file = new QFile(filename);
was not getting complete file path while opening the file as filename had only names.
Replace it with:
file = new QFile(directory.filePath(filename)); - file.close(); Removed the following line.
After that it got up and running.
Just for confirmation. I am getting code 200 in reply. If the file have been actually uploaded will i have to check the server for file or can be done in code ?
- file = new QFile(filename);
-
@Kira said in Issue in Uploading Image file using post method::
Just for confirmation. I am getting code 200 in reply.
See here for the meaning of that HTTP response code:
200 OK
The request has succeeded. The meaning of the success depends on the HTTP method:
...
PUT or POST: The resource describing the result of the action is transmitted in the message body.If the file have been actually uploaded will i have to check the server for file or can be done in code ?
Given you receive status code 200 you're done, the server is telling you the request was processed Ok.
What if the server your posting the files to is just all across the world? You won't be able to check the file was actually written to the server's file system.
After receiving the response Ok, you could GET the file from the server and compare it with the copy you have, but that's paranoid work it seems...
-
Hi everyone,
I have modified my code as follows:QUrl apiEndpoint(QString::fromStdString(_config->GetAPIEndpoint())); QDir directory(QString::fromStdString(path)); QStringList images = directory.entryList(QDir::Files); QNetworkRequest request; QNetworkReply* reply; QFile* file; foreach(QString filename, images) { file = new QFile("C:\\Studies\\upload.jpeg"); file->open(QIODevice::ReadOnly ); QHttpMultiPart* multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType); QHttpPart imagePart; imagePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"file\"; filename=\"" + file->fileName() + "")); imagePart.setBodyDevice(file); file->setParent(multiPart); multiPart->append(imagePart); request.setUrl(apiEndpoint); reply = _manager->post(request, multiPart); qDebug() << "Reply" << reply->readAll(); qDebug() << "Error" << reply->error(); qDebug() << "Status" << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute); }
I am getting the following error:
Reply Error: QNetworkReply::NetworkError(NoError) -
@Kira said in Issue in Uploading Image file using post method::
I am getting the following error:
And what's the problem now? The API is asynchronous...
-
@Christian-Ehrlicher : yes
-
@Kira
with asynchronous, Mr @Christian-Ehrlicher means thatreply = _manager->post(request, multiPart); // start the post process. and do not wait until finished and goes to next line
qDebug() << "Reply" << reply->readAll(); // there might not be anything to read yet
qDebug() << "Error" << reply->error(); // might be no errors to report yetSo in short use the signals +slot/lambdas for this :)
-
@mrjj : Thanks for the clarification.
What you said is correct.
I was getting error was because nothing was ready, neither response nor error.
The program I have written is asynchronous. I have used signals and slots, but the actual problem was I had not allocated memory on the heap while creating the class object.
I had created the object inside the QPushButton slot, and memory got allocated on the stack the object got destroyed before the response got
generated.
This scenario also brings me to a question:
If we allocate memory on the heap and response is generated when the object will get released from memory, or is it likely to cause a memory leak?
This scenario often occurs when allocating memory for the widgets. How the memory management gets done and when do we have to delete the objects manually. -
@Kira
Ah. ok. it was not clear from code.
So it was out of scope issue.
Well many Qt classes take a pointer to a parent. it will auto clean up any
children it owns. ( like forms delete all its buttons etc )
So in most cases, you dont have to do it manually.https://doc.qt.io/qt-5/objecttrees.html
QNetworkReply being an exception i think.
-
As long as there is software, there will be issues ;)