Иногда возникает вполне понятная нужда создания приложения, которое отправляет данные (в т.ч. по частям) на сервер, к примеру, загружая фотографию или просто «вставляя» данные в форму на сайте.
В интернете достаточно мало примеров и информации как это сделать. За основу легко можно брать веб-форму для данной операции, т.к. из ее организации легко понять как сформировать нужный нам запрос.
Правда в первую очередь советую прочитать что такое HTTP запросы, в частности искомый POST. В интернете полным-полно детальных описаний, к примеру вот. Я же перейду сразу к практике.
Ниже привожу код примера.
QNetworkRequest request; request.setUrl(QUrl("http://yoursite.com/uploadgate/")); request.setRawHeader("Host", "yoursite.com"); request.setRawHeader("Content-type", "multipart/form-data, boundary=AyV04a"); request.setRawHeader("Cache-Control", "no-cache"); request.setRawHeader("Accept","*/*"); QByteArray bytes; bytes.append("--AyV04a\r\n"); bytes.append("content-disposition: "); bytes.append("form-data; name=\" __PARAM_NAME__ \"\r\n"); bytes.append("\r\n"); bytes.append( __your PARAM_NAME data in TEXT__ ); bytes.append("\r\n"); bytes.append("--AyV04a\r\n"); bytes.append("content-disposition: "); bytes.append("file; name=\"file\"; filename=\" __FILE_NAME__ \"\r\n"); bytes.append("Content-Transfer-Encoding: binary\r\n"); bytes.append("\r\n"); bytes.append( __file BINARY data__ ); bytes.append("\r\n"); bytes.append("--AyV04a--"); QNetworkAccessManager* pManager = new QNetworkAccessManager(); QNetworkReply *reply = pManager->post(request, bytes);
Соответственно, первым делом формируем заголовок (header) нашего запроса, а затем уже — оформляем данные для отправки. Такая штука как boundary — определяет разделы запроса, чаще всего — просто случайно генерированная строка.
__PARAM_NAME__ — просто название параметра, для которого отсылаются данные, к примеру name для имени пользователя в форме отправки имени.
Для отправки файлов используется структура, описанная с __FILE_NAME__ вставкой. Не забывайте, что данные чаще всего передаются именно в двоичном формате. В нашем случае это будет QByteArray.
В принципе, пример достаточно прозрачный, если какие-либо вопросы, пишите.
Comments
[...] многопоточная отправка файла по частям на сервер (недавняя статья про POST multipart/form-data), я пришел к решению, означенному выше. Сутью такого [...]
Добрый день. Пытаюсь скомпилировать данный пример, но креатор сильно ругается вот так:
C:\Qt\Qt5.0.1\Tools\QtCreator\bin\prac_cons-build-Desktop_Qt_5_0_1_MinGW_32bit-_______/../prac_cons/main.cpp:25: undefined reference to `_imp___ZN15QNetworkRequestC1ERK4QUrl’
C:\Qt\Qt5.0.1\Tools\QtCreator\bin\prac_cons-build-Desktop_Qt_5_0_1_MinGW_32bit-_______/../prac_cons/main.cpp:26: undefined reference to `_imp___ZN15QNetworkRequest6setUrlERK4QUrl’
C:\Qt\Qt5.0.1\Tools\QtCreator\bin\prac_cons-build-Desktop_Qt_5_0_1_MinGW_32bit-_______/../prac_cons/main.cpp:28: undefined reference to `_imp___ZN15QNetworkRequest12setRawHeaderERK10QByteArrayS2_’
C:\Qt\Qt5.0.1\Tools\QtCreator\bin\prac_cons-build-Desktop_Qt_5_0_1_MinGW_32bit-_______/../prac_cons/main.cpp:42: undefined reference to `_imp___ZN21QNetworkAccessManagerC1EP7QObject’
C:\Qt\Qt5.0.1\Tools\QtCreator\bin\prac_cons-build-Desktop_Qt_5_0_1_MinGW_32bit-_______/../prac_cons/main.cpp:43: undefined reference to `_imp___ZN21QNetworkAccessManager4postERK15QNetworkRequestRK10QByteArray’
C:\Qt\Qt5.0.1\Tools\QtCreator\bin\prac_cons-build-Desktop_Qt_5_0_1_MinGW_32bit-_______/../prac_cons/main.cpp:49: undefined reference to `_imp___ZN15QNetworkRequestD1Ev’
C:\Qt\Qt5.0.1\Tools\QtCreator\bin\prac_cons-build-Desktop_Qt_5_0_1_MinGW_32bit-_______/../prac_cons/main.cpp:25: undefined reference to `_imp___ZN15QNetworkRequestD1Ev’
C:\Qt\Qt5.0.1\Tools\QtCreator\bin\prac_cons-build-Desktop_Qt_5_0_1_MinGW_32bit-_______/../prac_cons/main.cpp:49: undefined reference to `_imp___ZN15QNetworkRequestD1Ev’
collect2.exe: error: ld returned 1 exit status
исходный код:
#include
#include
#include
#include
#include
#include
#include
#include
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QFile file;
QByteArray data;
file.setFileName(«tmp.flac»);
file.open(QIODevice::ReadOnly);
file.write(data);
file.close();
QNetworkRequest request;
request.setUrl(QUrl(«https://www.google.com/speech-api/v1/recognize?xjerr=1&client=chromium&lang=ru-RU»));
request.setRawHeader(«Content-type», «audio/x-flac; rate=16000, boundary=AyV04a»);
QByteArray bytes;
bytes.append(«—AyV04a\r\n»);
bytes.append(«content-disposition: «);
bytes.append(«file; filename=\» tmp.flac \»\r\n»);
bytes.append(«Content-Transfer-Encoding: binary\r\n»);
bytes.append(«\r\n»);
bytes.append(data);
bytes.append(«\r\n»);
bytes.append(«—AyV04a—»);
QNetworkAccessManager* pManager = new QNetworkAccessManager();
QNetworkReply *reply = pManager->post(request, bytes);
return a.exec();
}
Скажите, что я мог сделать не так?
Пробуй в .pro файле прописать Qt+=network