http Multi part file upload via post request doesn't work in Windows



  • 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();  
    

  • Lifetime Qt Champion

    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.



  • 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?



  • Here is the communication log from from wireshark during the file upload if it helps. Last line arrived exactly when QT networkreply gave QNetworkReply::RemoteHostClosedError
    0_1485051950363_Capture.PNG


  • Lifetime Qt Champion

    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.



  • 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;
    }
    

  • Lifetime Qt Champion

    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.



  • @fastcoder I have the same issue but in the opposite direction. Everything works in Windows but not in MacOS.



  • In my case I had processEvents() function called in uploadProgress function. When I get rid of it the problem was solved.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.