четверг, 28 июля 2016 г.

GET и POST запросы в Qt 5.4.2 и Qt 5.7

Что-то я совсем забросил свой блог, пора наверстывать упущенное. Итак, ныне очень актуально писать мобильные и десктопные приложения, которые общаются с сервером с помощью HTTP запросов и есть довольно частая проблема с тем, как заставить их работать. Данный пример писался на Qt + node.js для backend. Версия Qt 5.4.2, но и на 5.7 код не должен отличаться.

Стандартная форма GET запроса имеет следующий вид:
http://www.site.ru/zapros?value1=data1&value2=data2
В данном запросе мы отправляет GET запрос на site.ru по ссылку zapros и передаем два параметра, value1 и value2. На Qt это будет выглядеть следующим образом:

    QNetworkRequest request(QUrl("http://www.site.ru/zapros?value1=data1&value2=data2"));
    QNetworkAccessManager mngr = new QNetworkAccessManager(this);
    mngr->get(request);

Мы отправили запрос, но в данном случае это отправка данных в один конец. Если же мы хотим получить ответ на этот запрос, то нам необходимо подключить функцию-обработчик ответа на запрос. В упрощенном виде это будет выглядеть следующим образом:

void Communicator::sendData() {
    QNetworkRequest request(QUrl("http://www.site.ru/zapros?value1=data1&value2=data2"));
    QNetworkAccessManager *mngr = new QNetworkAccessManager(this);
    connect(this, mngr, SIGNAL(finished(QNetworkReply*)), SLOT(getResponse(QNetworkReply*)));
    mngr->get(request);
}

void Communicator::getResponse(QNetworkReply *reply)
{
    qDebug() << reply->readAll();
}

Есть некоторый класс Communicator, для которого созданы 2 слота, sendData() и getResponse()
В первом мы отправляем данные, во втором получаем и выводим их в консоль.

POST запросы имеют ту же логику, но значительно сложнее по начинке. В данном случае я приведу сложный, но очень нужный на практике пример - передача нескольких параметров + файла. Вся соль будет в составе запроса

    QNetworkRequest request(QUrl("http://site.ru/api/uploadFile")); //our server with php-script
    QString bound="margin"; //name of the boundary
    //according to rfc 1867 we need to put this string here:
    QByteArray data = ("--margin\r\n");
    data.append("Content-Disposition: form-data; name=\"hash\"\r\n\r\n");
    data.append( hash + "\r\n");
    data.append("--" + bound +"\r\n");
    data.append("Content-Disposition: form-data; name=\"absolutePath\"\r\n\r\n");
    data.append(fileInfo.absoluteFilePath() + "\r\n");
    data.append("--" + bound + "\r\n"); //according to rfc 1867
    data.append("Content-Disposition: form-data; name=\"datetime\"\r\n\r\n");
    data.append(fileInfo.lastModified().toString(Qt::ISODate) + "\r\n");
    data.append("--" + bound + "\r\n"); //according to rfc 1867
    data.append("Content-Disposition: form-data; name=\"created\"\r\n\r\n");
    data.append(fileInfo.created().toString(Qt::ISODate) + "\r\n");
    data.append("--" + bound + "\r\n"); //according to rfc 1867
    data.append("Content-Disposition: form-data; name=\"upload\"; filename=\"" + fileInfo.fileName() + "\"\r\n");
    data.append("Content-Type: " + fileInfo.fileName().split(".").last() + "\r\n\r\n");
    QFile file(fileInfo.absoluteFilePath());
    if (!file.open(QIODevice::ReadOnly))
    return;
    data.append(file.readAll()); //let's read the file
    data.append("\r\n");
    data.append("--margin--\r\n"); //closing boundary according to rfc 1867
    request.setRawHeader("Content-Type","multipart/form-data; boundary=margin");
    request.setRawHeader("Content-Length", QString::number(data.length()).toUtf8());
    //connect(manager, SIGNAL(finished(QNetworkReply*)), SLOT(sendingFinished(QNetworkReply*)));
    QNetworkReply *reply = manager->post(request,data);
    connect(reply, SIGNAL(uploadProgress(qint64,qint64)), SLOT(downloadProgress(qint64,qint64)));
    connect(reply, SIGNAL(finished()), SLOT(sendingFinished()));
    managerIsSending = true;
    qDebug() << Q_FUNC_INFO << "finished for " << "file path" << fileInfo.absoluteFilePath();
}
Что здесь происходит? Есть некоторый массив данных, именуемый data. Мы его наполняем несколькими переменными, необходимыми для сервера, такими как hash, absolutePath и т.д. Эти данные были необходимы именно мне, в общем случае они не являются обязательными и вы можете заменить их своими данными или вообще убрать.
В конце мы к этим данным добавляем содержимое файла, после этого добавляем некоторые обязательно параметры для запроса и пишем всё в
manager.
На выходе вы получаете отправку файла и некоторых переменных на сервер.

Комментариев нет:

Отправить комментарий