http Multi part file upload via post request doesn't work in Windows
-
wrote on 21 Jan 2017, 02:43 last edited by fastcoder
I am trying to upload a file (~3Mb) to a server via http multipart post request in QT.The same code uploads successfully on MacOSx without any problems,however in windows 10 (didnt try with 7 or 8) QNetworkReply never emits finish signal and doesn't update upload progress at all. If I remove the file part from post request or choose a file which is 1kb then it also works with windows 10. If i wait long enough then I receive QNetworkReply::RemoteHostClosedError
Here is my function to upload a file.QErrorMessage msg; QString filename="some_file_name.zip"; QFile *file=new QFile(filename); if(!file->open(QIODevice::ReadOnly)) { msg.showMessage("File couldnt be found, upload failed"); msg.exec(); return false; } uploadProgressBar = new QProgressDialog("Uploading...", "cancel", 0, 100); QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType); QHttpPart productIDpart; productIDpart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"ProductId\"")); productIDpart.setBody("123"); multiPart->append(productIDpart); QHttpPart filePart; filePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("application/zip")); filePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"File\";filename=\"some_file_name.zip\" ")); filePart.setBodyDevice(file); file->setParent(multiPart); // we cannot delete the file now, so delete it with the multiPart multiPart->append(filePart); QNetworkAccessManager manager; QUrl serviceUrl = QUrl("http://someserver.com/"); QNetworkRequest request(serviceUrl); request.setRawHeader( "AuthenticationKey",authenticationKey.toUtf8()); QEventLoop eventLoop; QNetworkReply *reply = manager.post(request, multiPart); connect(uploadProgressBar, SIGNAL(canceled()),reply,SLOT(abort())); connect(reply, SIGNAL(metaDataChanged()), reply, SLOT(abort())); connect(reply, SIGNAL(uploadProgress(qint64, qint64)),this,SLOT(uploadProgress(qint64, qint64))); connect(reply, SIGNAL(finished()), &eventLoop, SLOT(quit())); multiPart->setParent(reply); //When uploading a file larger than 3-4Kb the code stucks at below line. //however the same code uploads on Mac OSx without any problems eventLoop.exec();
-
Hi and welcome to devnet,
You should add additional error checks as well as connect the error related signals, you might be hitting something on Windows that doesn't occur on macOS.
On a side note, you have memory leak with your file object. Since you're "blocking" the function until the upload is done. You should keep that variable on the stack.
-
wrote on 22 Jan 2017, 00:41 last edited by
Thank you very much for your reply, I was already printing the error code returned by QNetworkReply::error() function when the eventLoop quits as a result of finished() signal emitted by the reply. After 1-2 minutes the error code returned was QNetworkReply::RemoteHostClosedError. What other error checks should I be doing?
-
wrote on 22 Jan 2017, 02:27 last edited by
-
The upload functionality of the forum is currently broken. Please use an image sharing site and post the link.
You shouldn't wait for the loop to end to gather the information. You should connect the QNetworkReply::error signal.
-
wrote on 23 Jan 2017, 23:02 last edited by fastcoder
after your suggestion I complemented with the below lines however still not catching any errors before the server really kills the connection. Here is the screenshot from wireshark just before the communication ends with QNetworkReply::RemoteHostClosedError http://www.imageno.com/rxgfgmc2bt2tpic.html
as an additional information right after the uploadprogress callback is called with 0%, I see a lot of thread exited information at the console
Uploading 16384 / 2634392 % 0
The thread 0x1ac4 has exited with code 0 (0x0).
The thread 0x698 has exited with code 0 (0x0).
The thread 0x2448 has exited with code 0 (0x0).interesting point is during the upload even if I close my wifi connection, still it doesnt come to the error callback. It comes to the error call back only if I press cancel button of upload dialog or wait 2-3 minutes.
QNetworkReply *reply = manager.post(request, multiPart); connect(uploadProgressBar, SIGNAL(canceled()),reply,SLOT(abort())); connect(reply, SIGNAL(uploadProgress(qint64, qint64)),this,SLOT(uploadProgress(qint64, qint64))); connect(reply, SIGNAL(finished()), &eventLoop, SLOT(quit())); connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(error(QNetworkReply::NetworkError))); connect(reply, SIGNAL(sslErrors(const QList<QSslError>)), this, SLOT(error(const QList<QSslError>))); multiPart->setParent(reply); // delete the multiPart with the reply //When uploading a file larger than 3-4Kb the code stucks at below line. //however the same code uploads on Mac OSx without any problems eventLoop.exec(); if (reply->error() == QNetworkReply::NoError) { QString strReply = (QString)reply->readAll(); //parse json qDebug() << "Response:" << strReply; QJsonDocument jsonResponse = QJsonDocument::fromJson(strReply.toUtf8()); QJsonObject jsonObj = jsonResponse.object(); QJsonObject result=jsonObj["result"].toObject(); if(jsonObj["error"].toBool()==false) { QJsonObject data=result["data"].toObject(); QrLink=data["QrLink"].toString(); QMessageBox msgBox; msgBox.setText("model is uploaded"); msgBox.exec(); } else { QErrorMessage msg; msg.showMessage("Error during upload proces"); msg.exec(); } delete reply; } else { QErrorMessage msg; int code= reply->error(); msg.showMessage("Upload couldn't start"+ QString::number(code)); msg.exec(); } delete file; } return true; } void error(const QList<QSslError> &errors) { qDebug() << errors; } void error(QNetworkReply::NetworkError error) { qDebug() << error; }
-
You should also connect the error signal to the quit slot, that way you don't have to "influence" the system to make it go further and thus maybe modify its outcome.
-
wrote on 24 Feb 2017, 06:01 last edited by
@fastcoder I have the same issue but in the opposite direction. Everything works in Windows but not in MacOS.
-
wrote on 25 Feb 2017, 03:39 last edited by
In my case I had processEvents() function called in uploadProgress function. When I get rid of it the problem was solved.