Results 1 to 2 of 2

Thread: Upload file to CloudApp problem

  1. #1
    Join Date
    Jan 2006
    Posts
    46
    Thanks
    2
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default Upload file to CloudApp problem

    Hi guys,

    I'm having a problem when uploading a file to getcloudapp.com (CloudApp).
    I'm following the instructions from the API documentation:

    First a request for a new upload as shown here https://github.com/cloudapp/api/blob...uest-to-upload

    Using a QNetworkAccessManager instance:

    Qt Code:
    1. QUrl url("http://my.cl.ly/items/new");
    2. QNetworkRequest request(url);
    3.  
    4. request.setRawHeader("Accept", "application/json");
    5. networkManager->get(request);
    To copy to clipboard, switch view to plain text mode 

    The networkManager instance's finished(QNetworkReply*) signal is connected to a slot that processes the response shown in the API Documentation to make a new post for the actual upload:

    Qt Code:
    1. void QCloudFileUploader::uploadFile(QNetworkReply *reply)
    2. {
    3. QByteArray data = reply->readAll();
    4. QJsonParseError error;
    5. QJsonDocument document = QJsonDocument::fromJson(data, &error);
    6. QJsonObject response = document.object();
    7.  
    8. QJsonObject params = response.take("params").toObject();
    9. QHttpPart AWSKey;
    10. QHttpPart key;
    11. QHttpPart policy;
    12. QHttpPart signature;
    13. QHttpPart successRedirect;
    14. QHttpPart acl;
    15. QHttpPart filePart;
    16. QMimeDatabase mime;
    17.  
    18. QUrl url(response.take("url").toString());
    19. QHttpMultiPart *fileData = new QHttpMultiPart(this);
    20. QCloudFileUploadThread *thread = uploaders.take(uploaders.keys().at(0));
    21.  
    22. AWSKey.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"AWSAccessKeyId\""));
    23. AWSKey.setBody(params["AWSAccessKeyId"].toString().toUtf8());
    24. fileData->append(AWSKey);
    25.  
    26. key.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"key\""));
    27. key.setBody(params["key"].toString().toUtf8());
    28. fileData->append(key);
    29.  
    30. policy.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"policy\""));
    31. policy.setBody(params["policy"].toString().toUtf8());
    32. fileData->append(policy);
    33.  
    34. signature.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"signature\""));
    35. signature.setBody(params["signature"].toString().toUtf8());
    36. fileData->append(signature);
    37.  
    38. successRedirect.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"success_action_redirect\""));
    39. successRedirect.setBody(params["success_action_redirect"].toString().toUtf8());
    40. fileData->append(successRedirect);
    41.  
    42. acl.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"acl\""));
    43. acl.setBody(params["acl"].toString().toUtf8());
    44. fileData->append(acl);
    45.  
    46. QNetworkRequest request(url);
    47.  
    48. QFile *file = new QFile(thread->fileName());
    49. file->open(QIODevice::ReadOnly);
    50.  
    51. if (file->error() != QFile::NoError)
    52. {
    53. qDebug(file->errorString().toLatin1());
    54. return;
    55. }
    56.  
    57. QFileInfo fi(file->fileName());
    58.  
    59. QString contentDisposition = "form-data; name=\"file\"; filename=\"" + fi.completeBaseName() + "." + fi.completeSuffix() + "\"";
    60. qDebug(contentDisposition.toLatin1());
    61.  
    62. filePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant(mime.mimeTypeForData(file).name()));
    63. filePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant(contentDisposition));
    64. filePart.setBodyDevice(file);
    65. file->setParent(fileData);
    66. fileData->append(filePart);
    67.  
    68. QNetworkReply *reply = networkManager->post(request, fileData);
    69.  
    70. connect(reply, SIGNAL(uploadProgress(qint64,qint64)), this, SLOT(notifyUpload(qint64,qint64)));
    71. connect(reply, SIGNAL(finished()), this, SLOT(notifyUploadFinish()));
    72. }
    To copy to clipboard, switch view to plain text mode 

    Don't pay too much attention to the code design, my intention here is to spot any error I might be missing.
    The uploadProgress slot is reporting the file is uploaded completely. I'm skipping it here for clarity's sake.
    The notifyUploadFinish() slot is getting the response of the POST request once it has finished and all looks OK:

    Qt Code:
    1. void QCloudFileUploader::notifyUploadFinish()
    2. {
    3. finishedUploaders++;
    4. qDebug("Finishing");
    5.  
    6. QNetworkReply *reply = (QNetworkReply*)sender();
    7.  
    8. if (reply->attribute(QNetworkRequest::HttpStatusCodeAttribute) == 303)
    9. {
    10. qDebug(QString(reply->rawHeader("Location")).toLatin1());
    11. QUrl url(QString(reply->rawHeader("Location")));
    12. QNetworkRequest request(url);
    13. reply = networkManager->get(request);
    14. connect(reply, SIGNAL(finished()), this, SLOT(redirectFinished()));
    15. return;
    16. }
    17.  
    18. qDebug(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toString().toLatin1());
    19. qDebug("HTTP Redirection Target");
    20. qDebug(reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toString().toLatin1());
    21. qDebug("HTTP Reason Phrase");
    22. qDebug(reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString().toLatin1());
    23. }
    To copy to clipboard, switch view to plain text mode 

    The API documentation for upload to S3 says the response should be a "303 See Other" (which is what I'm receiving), so then you need to ping CloudApp to get the details of the new file.

    According to Qt documentation, Qt doesn't follow redirections so you need to do it manually. That's what I do if the response is 303, the location header looks like:
    Qt Code:
    1. http://my.cl.ly/items/s3?bucket=f.cl.ly&key=items0.0000002V1n29090S1u2f3j0t230.000000arch-tux.png&etag=%22b3e0682a5bdaa51eb2a342a4ea77aa0f%22
    To copy to clipboard, switch view to plain text mode 

    For that GET request I'm getting a 302 response with the body:

    Qt Code:
    1. <html><body>You are being <a href="http://my.cl.ly/">redirected</a>.</body></html>
    To copy to clipboard, switch view to plain text mode 

    So, no details as expected and the file is not shown under my account.

    What caught my attention is that the get request does not get authenticated again, I'm assuming that's because the QNetworkAccessManager instance keeps the session information, but that's just a guess.

    I've already tried posting the file to a local web application for debugging purposes and I could verify the params are sent correctly, I could even open the temp file generated by the web application and check it has the proper contents.

    Also, I tried changing the parameters, and I saw different errors, so I could assume the parameters are correct like this.

    Any clue would be very much appreciated.

    Thanks a lot in advance.
    Kandalf
    There's no place like ~

  2. #2
    Join Date
    Jan 2006
    Posts
    46
    Thanks
    2
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default [SOLVED] Upload file to CloudApp problem

    I solved it. The problem was the Accept header in the GET request to the uploaded file.

    So, basically adding the header like below:
    Qt Code:
    1. //Look at the 3rd code block in the post
    2.  
    3. if (reply->attribute(QNetworkRequest::HttpStatusCodeAttribute) == 303)
    4. {
    5. qDebug(QString(reply->rawHeader("Location")).toLatin1());
    6. QUrl url(QString(reply->rawHeader("Location")));
    7. QNetworkRequest request(url);
    8. request.setRawHeader("Accept", "application/json");
    9. reply = networkManager->get(request);
    10. connect(reply, SIGNAL(finished()), this, SLOT(redirectFinished()));
    11. return;
    12. }
    To copy to clipboard, switch view to plain text mode 

    Will turn the 302 into a 200 with the metadata of the uploaded file in the body in a JSON format.

    Hope it helps.
    Last edited by kandalf; 19th November 2014 at 02:44. Reason: Changes title to solved
    Kandalf
    There's no place like ~

Similar Threads

  1. Problem in Http file upload
    By dipeshtech in forum Qt Programming
    Replies: 1
    Last Post: 28th April 2011, 08:44
  2. Replies: 1
    Last Post: 21st October 2010, 04:59
  3. Qhttp Upload file
    By danny.lesnik in forum Qt Programming
    Replies: 5
    Last Post: 11th December 2009, 09:02
  4. QNetworkRequest file upload -- please help
    By Runtime Technologies in forum Qt Programming
    Replies: 3
    Last Post: 14th July 2009, 15:55
  5. QHttp "PUT METHOD" QT Problem File Upload. RFC 2616
    By patrik08 in forum Qt Programming
    Replies: 7
    Last Post: 25th October 2006, 22:02

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.