Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. How to post QHttpPart with sequential QIODevice
Forum Updated to NodeBB v4.3 + New Features

How to post QHttpPart with sequential QIODevice

Scheduled Pinned Locked Moved General and Desktop
8 Posts 2 Posters 4.3k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    matejk
    wrote on last edited by
    #1

    I am writing an application that is posting data as http multipart to a server. One of the parts is ordinary text, the other part is read from a sequential QIODevice.

    Post with QNAM hangs after all of the data is read from the device.

    There is a note in the "documentation":http://qt-project.org/doc/qt-4.8/qhttppart.html that:

    bq. if device is sequential (e.g. sockets, but not files), QNetworkAccessManager::post() should be called after device has emitted finished().

    However "QIODevice":http://qt-project.org/doc/qt-4.8/qiodevice.html doesn't emit finished() at all. Is there an error in the documentation?

    I tried to use my custom sequential QIODevice as I would use a file. All data was read from the device after QNAM::post was called, but then sending hanged. Without calling post, reading didn't start at all.

    This looks like catch 22: post() expects finished() to be emitted, but no data is read before post() is called...

    What is the proper way to use sequential QIODevice with QHttpMultipart?

    @QHttpMultiPart *multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);

    QHttpPart metaPart;
    metaPart.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
    metaPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name="metadata""));
    metaPart.setBody(meta.toJson());
    multiPart->append(metaPart);

    QHttpPart filePart;
    filePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant(fileFormat));
    filePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name="file""));
    filePart.setBodyDevice(p_encDevice);
    p_encDevice->setParent(multiPart); // we cannot delete the device now, so delete it with the multiPart
    multiPart->append(filePart);

    QNetworkAccessManager netMgr;
    QScopedPointer<QNetworkReply> reply( netMgr.post(request, multiPart) );
    multiPart->setParent(reply.data()); // delete the multiPart with the reply
    @

    1 Reply Last reply
    0
    • M Offline
      M Offline
      matejk
      wrote on last edited by
      #2

      Qt5 Documentation for "QHttpPart::setBodyDevice":http://qt-project.org/doc/qt-5.0/qtnetwork/qhttppart.html#setBodyDevice contains the same instructions.

      Can anyone with experience using sequential devices in QHttpMultipart provide me insights, please?

      1 Reply Last reply
      0
      • M Offline
        M Offline
        matejk
        wrote on last edited by
        #3

        I asked the same question on stackoverflow, but I didn't receive any useful answer:

        http://stackoverflow.com/questions/15109656/qnetworkaccessmanager-post-http-multipart-from-serial-qiodevice

        1 Reply Last reply
        0
        • S Offline
          S Offline
          sl.sy.ifm
          wrote on last edited by
          #4

          As far as I can see the QHttpMultiPart and QNetworkReply... try to read until the device returns -1 when calling read(...)
          Make sure that your implementation of readData(...) returns -1 when it gets called after all data was already read!

          ... as QHttpMultiPart doesn't listen to any signales, the signals of your device don't care, it's all about the return-code of read/readData

          1 Reply Last reply
          0
          • M Offline
            M Offline
            matejk
            wrote on last edited by
            #5

            Thanks for tips. My code returns -1 when all data is read. I am posting the trace from my class after QNAM::post() is called.

            As you can see there is a read request for more data than actually available. This is the only call to readData of my class. Next call would return -1, however this call doesn't happen.

            @
            [13-03-12 13:51:56.091] isSequential
            [13-03-12 13:51:56.092] isSequential
            [13-03-12 13:51:56.100] size: 70925
            [13-03-12 13:51:56.101] isSequential
            [13-03-12 13:51:56.121] size: 70925
            [13-03-12 13:51:56.122] isSequential

            readData -->
            [13-03-12 13:51:56.157] Read request: 70972
            [13-03-12 13:51:56.158] Read from source: 70917
            [13-03-12 13:51:56.160] Reached source EOF.
            [13-03-12 13:51:56.161] Completing encryption of message.
            [13-03-12 13:51:56.163] Return: 70925 , remains 0
            <-- readData

            [13-03-12 13:51:56.163] size: 70925
            [13-03-12 13:51:56.164] size: 70925
            [13-03-12 13:51:56.165] size: 70925

            -- everything stops here --
            @

            1 Reply Last reply
            0
            • S Offline
              S Offline
              sl.sy.ifm
              wrote on last edited by
              #6

              I first was a bit puzzled how situation is exactly ... so I setup a small project to reproduce it and I also get to the point that it reads (on my case it even reads with -1 twice) ...

              As I was now confused what all the "isSequential" special handling should do, I changed it to return false (even so my device acts like sequential) ... and then it worked, it generated the data and send it to my webserver ... not sure what the side-effect of this is

              1 Reply Last reply
              0
              • S Offline
                S Offline
                sl.sy.ifm
                wrote on last edited by
                #7

                Btw. I think the code which queries isSequential() interprets it as "device doesn't know his size" ... and the QNAM code that follows on isSequential==true buffers all data from the device (probably to calculate a valid content-length) ...

                I haven't saw any code that use the other aspects of "isSequential" (like seek() or pos()) ... so if you could calculate the size and don't want the data to be buffered, isSequential==false and a valid size seems to be the right way

                ... but that still doesn't explain why QHttpMultiPart with isSequential doesn't work ... looking into unit-tests ... btw. THERE IS NO UNIT TEST for isSequential-Devices in the unit-tests for QHttpPart, so if this code is broken it wouldn't be detected anyway ...

                1 Reply Last reply
                0
                • M Offline
                  M Offline
                  matejk
                  wrote on last edited by
                  #8

                  Thanks. I was reviewing the Qt code as well. Your post confirms what I suspect.

                  1 Reply Last reply
                  0

                  • Login

                  • Login or register to search.
                  • First post
                    Last post
                  0
                  • Categories
                  • Recent
                  • Tags
                  • Popular
                  • Users
                  • Groups
                  • Search
                  • Get Qt Extensions
                  • Unsolved