The Simplest and Most Formal Method for Simulating POST Forms (Multipart Form) in Qt HTTP GET and POST

Note: Please indicate the source when reprinting, all rights reserved.Note: This is based on my own understanding,if it conflicts with your principles and ideas, please forgive me, do not criticize.

Environment Description

  Ubuntu 16.04 LTS  Packet capture tool: Wireshark

Introduction

  None

Qt HTTP

  1. 1. The three main classes related to Qt networking are QNetworkAccessManager, QNetworkRequest, and QNetworkReply. The general usage method is: QNetworkRequest adds headers and address information, QNetworkAccessManager initiates the request, and QNetworkReply handles the server’s response.
  2. 2. Regarding the implementation of general POST and GET in Qt, we can simply refer to the help documentation as shown in the figure below.

  From here we can see that for GET, we just need to fill in the request information and hand it over to the manager for submission. The focus should be on the overloaded functions for POST. This article will only analyze the second and third functions; I have not used the first one, so I am not clear about it.

QNetworkReply *post(const QNetworkRequest &request, const QByteArray &data) // This function simulates a form request in a very straightforward manner, although it is somewhat complex, it is definitely intuitive and effective.

QNetworkReply *post(const QNetworkRequest &request, QHttpMultiPart *multiPart) // This function is the official method for multi-part POST provided by Qt.
  1. 3. Before diving into the specifics, I must mention some aspects of the HTTP protocol. (I strongly recommend using Wireshark for analyzing various network protocols; it clearly displays the content in the five-layer network structure.)

    3.1 Below is a screenshot of a typical HTTP request capture (open the CSDN official website).

  The image shows the content of a typical HTTP GET request. The fields we need to focus on are User-Agent, Accept, and GET.

  The above image is a typical analysis of a POST multi-part request capture. We only need to focus on the Content-Type, which is the most important field. The subsequent MIME multipart section is the uploaded image. The most important part here is the boundary in the type, which is a unique string used for identification and as a separator for different fields in the form.

    3.2 For a detailed analysis of the HTTP protocol, please search online; I will not provide a detailed analysis here.

  1. 4. Regarding the official multipart form example code from Qt (this mainly involves QHttpMultiPart and QHttpPart) (the main part comes from the Qt help documentation, but this example has some issues).
    proc_request = new QNetworkRequest();
    proc_manager = new QNetworkAccessManager();          
    connect(proc_manager, SIGNAL(finished(QNetworkReply*)),
        this, SLOT(YOUR_SLOT_FUNCTION(QNetworkReply*))); // Connect to the slot function

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

  QHttpPart textPart;
  textPart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"text\""));
  textPart.setBody("my text");

  QHttpPart imagePart;
  imagePart.setHeader(QNetworkRequest::ContentTypeHeader, QVariant("image/jpeg"));
  imagePart.setHeader(QNetworkRequest::ContentDispositionHeader, QVariant("form-data; name=\"image\""));
  QFile *file = new QFile("image.jpg");
  file->open(QIODevice::ReadOnly);
  imagePart.setBodyDevice(file);
  file->setParent(multiPart); // We cannot delete the file now, so delete it with the multiPart

  multiPart->append(textPart);
  multiPart->append(imagePart);

  proc_request->setUrl("http://xxxxxxxxxxxxx");
//**************Self-added part****************************
QString bd = "fasdlkfjaslkdgj;lkadjglk;";
multiPart->setBoundary(bd.toLatin1());
proc_request->setHeader(QNetworkRequest::ContentTypeHeader,
"multipart/form-data;boundary=" + bd);
//****************Self-added part*************************
proc_manager->post(*proc_request, multiPart);

  Analysis of the above code: I do not know why, but only after I explicitly specified the boundary could I successfully submit the POST request, so the self-added part is very important; without it, it does not work. This was discovered during practical analysis. (The official explanation regarding this issue: Usually, you do not need to generate a boundary yourself; upon construction, the boundary is initiated with the string “boundary_.oOo._” followed by random characters, providing enough uniqueness to ensure it does not occur inside the parts themselves.)(The above states that we do not need to specify it explicitly; it will automatically add a boundary, but in my project, it did not work, so I specified it explicitly. If anyone else experiments and finds that it can successfully POST without specifying it, please let me know. Sigh, this is really frustrating. Time to clock out~~~~~~~~~)

Postscript

  None

References

  • • None

Donations, subscriptions, favorites, throwing bananas, coins, please follow the public account.

Note: Please respect original work, do not criticize if you dislike it.Note: Please indicate the source when reprinting, all rights reserved.Note: If you have any questions, please leave a message, and I will reply as soon as I see it.

Leave a Comment