📜 ⬆️ ⬇️

Sending a multipart / form-data request to Qt

Sometimes when developing a network application, there is a problem of uploading a file to the server, and not just like that, but as part of a completed http form. This is an example of a so-called multipart / form-data request. Standard Qt library methods do not allow this, so you have to get out on your own.

general information


So, first of all, you need to understand what our multipart / form-data request contains in such an interesting way?
If you look at an example from here , a typical query is the following:

 POST http://www.site.ru/news.html HTTP / 1.0 \ r \ n
 Host: www.site.ru \ r \ n
 Referer: http://www.site.ru/index.html\r\n
 Cookie: income = 1 \ r \ n
 Content-Type: multipart / form-data;  boundary = 1BEF0A57BE110FD467A \ r \ n
 Content-Length: 209 \ r \ n
 \ r \ n
 --1BEF0A57BE110FD467A \ r \ n
 Content-Disposition: form-data;  name = "login" \ r \ n
 \ r \ n
 Petya Vasechkin \ r \ n
 --1BEF0A57BE110FD467A \ r \ n
 Content-Disposition: form-data;  name = "password" \ r \ n
 \ r \ n
 qq \ r \ n
 --1BEF0A57BE110FD467A - \ r \ n

What we are particularly interested in in the headers is the boundary = 1BEF0A57BE110FD467A and Content-Length: 209 , after which the request body begins. The request consists of several parts, while the separator will be what is written as the boundary, the length of the request body must also be specified - this is the Content-Length field. The request body is everything from the first line --1BEF0A57BE110FD467A . In each section, the name is the name of the corresponding form field, after two line breaks \ r \ n \ r \ n there is a field value

To send a file, you must create a section of the following format:
')
 --1BEF0A57BE110FD467A \ r \ n
 Content-Disposition: form-data;  name = "news_file";  filename = "news.txt" \ r \ n
 Content-Type: application / octet-stream \ r \ n
 Content-Transfer-Encoding: binary \ r \ n
 \ r \ n
 But such news, which lies in the file news.txt \ r \ n

Here, in addition, the file name is specified - news.txt, as well as the data encoding in the Content-Transfer-Encoding field. There are several different encodings, including the presented binary - unencoded data. Given Qt's capabilities, base64 encoding is very convenient. If the file is not just some kind of (application / octet-stream), but of a known type, then you can specify this type in the Content-Type field, for example, Content-Type: image / png .

Simple example


Let us turn to the practical example of the formation of the request. We have:

// ++   Qt QNetworkAccessManager *manager; // 1 - - ,  2 -  QByteArray param1Name="param1" ,param1Value="value1"; QByteArray param2Name="param2", param2FileName="news.txt", param2ContentType="text/plain",param2Data="   ,     news.txt"; 

First we create the request body:

 //  QByteArray postData,boundary="1BEF0A57BE110FD467A"; //  postData.append("--"+boundary+"\r\n");// //  postData.append("Content-Disposition: form-data; name=\""); postData.append(param1Name); postData.append("\"\r\n\r\n"); //  postData.append(param1Value); postData.append("\r\n"); // 2 -  postData.append("--"+boundary+"\r\n");// //  postData.append("Content-Disposition: form-data; name=\""); postData.append(param2Name); //  postData.append("\"; filename=\""); postData.append(param2FileName); postData.append("\"\r\n"); //   postData.append("Content-Type: "+param2ContentType+"\r\n"); //  base64 postData.append("Content-Transfer-Encoding: base64\r\n\r\n"); // postData.append(param2Data.toBase64()); postData.append("\r\n"); //""  postData.append("--"+boundary+"--\r\n"); 

In the variable postData, we get a ready-made request body — all that remains is to send and remember to install additional request headers:

 QNetworkRequest request(QUrl("http://example.com/submit.php")); request.setHeader(QNetworkRequest::ContentTypeHeader, "multipart/form-data; boundary="+boundary); request.setHeader(QNetworkRequest::ContentLengthHeader, QByteArray::number(postData.length())); QNetworkReply *reply=manager->post(request,postData); 

Well, then - on the thumb track, as for any other requests.

Eventually...


The example given is, of course, too simple for everyday use. But based on it, you can easily implement a function, class or class library for each specific task, depending on the complexity of the requests you have to generate.

Useful information:
http://www.codenet.ru/webmast/php/HTTP-POST.php - description of filling http requests.
http://www.ietf.org/rfc/rfc2388.txt - Standard "Returning Values ​​from Forms: multipart / form-data"

Source: https://habr.com/ru/post/143168/


All Articles