Работа с QNetworkAccessManager
1. Простой пример.
1.1. Загрузить страницу сайта.
Для работы необходимо в файл проекта(*.pro) добавить модуль network
QT += core gui network
И подключить заголовочные файлы
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkRequest>
#include <QtNetwork/QNetworkReply>
#include <QUrl>
#include <QTextCodec> // для преобразования кодировки
Для вывода результата нам потребуется определить слот и указатель на сам менеджер в заголовке класса виджета:
private slots:
void on_pushButton_clicked();
void replyFinished(); // cлот, выполняемый при завершении запроса
private:
Ui::MainWindow *ui;
QNetworkAccessManager* manager;
Сам код:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->lineEdit->setText("http://avazart.zz.mu ");
// Создаем объект менеджера
manager = new QNetworkAccessManager(this);
}
void MainWindow::on_pushButton_clicked()
{
// берем адрес введенный в текстовое поле
QUrl url(ui->lineEdit->text());
// создаем объект для запроса
QNetworkRequest request(url);
// Выполняем запрос, получаем указатель на объект
// ответственный за ответ
QNetworkReply* reply= manager->get(request);
// Подписываемся на сигнал о готовности загрузки
connect( reply, SIGNAL(finished()),
this, SLOT(replyFinished()) );
}
void MainWindow::replyFinished()
{
QNetworkReply *reply=
qobject_cast<QNetworkReply *>(sender());
if (reply->error() == QNetworkReply::NoError)
{
// Получаем содержимое ответа
QByteArray content= reply->readAll();
// Реализуем преобразование кодировки
// (зависит от кодировки сайта)
QTextCodec *codec = QTextCodec::codecForName("utf8");
// Выводим результат
ui->textEdit->setPlainText(codec->toUnicode(content.data()) );
}
else
{
// Выводим описание ошибки, если она возникает.
ui->textEdit->setPlainText(reply->errorString());
}
// разрешаем объекту-ответа "удалится"
reply->deleteLater();
}
Если необходимо загрузить страницу с блокировкой, т.е. ждать загрузки потока можно применить QEventLoop :
#include <QEventLoop>
// ...
void MainWindow::on_pushButton_clicked()
{
QUrl url(ui->lineEdit->text());
QNetworkRequest request(url);
QNetworkReply* reply= manager->get(request);
// реализуем ожидание конца загрузки
QEventLoop loop;
connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
loop.exec();
// выводим содержимое
if (reply->error() == QNetworkReply::NoError)
{
QByteArray content= reply->readAll();
QTextCodec *codec = QTextCodec::codecForName("utf8"); // cp-1251
ui->textEdit->insertPlainText(codec->toUnicode(content.data()) );
}
else
{
ui->textEdit->setPlainText(reply->errorString());
}
reply->deleteLater();
}
1. 2. Загрузка в файл.
Для загрузки в файл используем QFile, изменяем код ответственный за вывод содержимого.
#include <QFile>
// ...
if (reply->error() == QNetworkReply::NoError)
{
QFile file("1.html");
if( file.open(QIODevice::WriteOnly) )
{
QByteArray content= reply->readAll();
file.write(content); // пишем в файл
}
}
else // вывод ошибки
ui->textEdit->setPlainText(reply->errorString());
reply->deleteLater();
1.3. Заголовки запроса и ответа.
Заголовки запроса устанавливаются в объекте QNetworkRequest.
QNetworkRequest request(url);
request.setHeader(
QNetworkRequest::UserAgentHeader,
"Mozilla/5.0 (Windows NT 6.1; rv:16.0) Gecko/20100101 Firefox/16.0"
);
request.setRawHeader(
"Accept",
"text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
);
request.setRawHeader(
"Accept-Language",
"ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3"
);
request.setRawHeader(
"Connection",
"keep-alive"
);
Заголовки ответа можно получить соответственно из объекта QNetworkReply, например таким образом можно получить заголовок «Location»
if( reply->hasRawHeader("Location"))
{
QString location= reply->header(QNetworkRequest::LocationHeader).toString();
ui->textEdit->insertPlainText("\nLocation: "+location);
}
2. Загрузка изображения.
Как пример код загрузки изображения на известный файлообменник rghost.ru
#include <QDebug>
#include <QFile>
#include <QFileDialog>
#include <QHttpMultiPart>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->lineEdit->setText("Я картинкО.jpg");
manager = new QNetworkAccessManager(this);
}
void MainWindow::on_pushButtonGo_clicked()
{
QString fileName= ui->lineEdit->text();
// Текст 1
QHttpPart textPart1;
textPart1.setHeader(
QNetworkRequest::ContentDispositionHeader,
QVariant("form-data; name=\"utf8\"") );
// Текст 2
QHttpPart textPart2;
textPart2.setHeader(
QNetworkRequest::ContentDispositionHeader,
QVariant("form-data; name=\"authenticity_token\"") );
// Картинка из файла
QHttpPart imagePart;
imagePart.setHeader(
QNetworkRequest::ContentTypeHeader, QVariant("image/jpeg"));
imagePart.setHeader(
QNetworkRequest::ContentDispositionHeader,
QVariant("form-data; name=\"file\"; filename=\""+
QFile(fileName).fileName().toHtmlEscaped()+
"\""));
QFile *file = new QFile(fileName);
if(!file->open(QIODevice::ReadOnly))
{
qDebug()<<"Can not open file!";
return;
}
imagePart.setBodyDevice(file);
// Собираем все части в целое
QHttpMultiPart* multiPart=
new QHttpMultiPart(QHttpMultiPart::FormDataType);
multiPart->append(textPart1);
multiPart->append(textPart2);
multiPart->append(imagePart);
file->setParent(multiPart); // we cannot delete the file now,
//so delete it with the multiPart
// Составляем запрос
QUrl url("http://phonon.rghost.ru/files ");
QNetworkRequest request(url);
QNetworkReply* reply= manager->post(request, multiPart);
multiPart->setParent(reply); // delete the multiPart with the reply
connect( reply, SIGNAL(finished()),
this, SLOT(replyFinished())
);
}
void MainWindow::replyFinished()
{
QNetworkReply *reply=
qobject_cast<QNetworkReply *>(sender());
if (reply->error() == QNetworkReply::NoError)
ui->textEdit->setHtml(reply->readAll());
else
ui->textEdit->setPlainText(reply->errorString());
reply->deleteLater();
}
void MainWindow::on_toolButtonOpenFile_clicked()
{
// Выбор файла через диалог занесение его lineEdit
QString fileName=
QFileDialog::getOpenFileName( this,
tr("Выбрать файл"),
QDir::currentPath(),
tr("Изображение (*.jpg)"));
if(!fileName.isEmpty())
ui->lineEdit->setText(fileName);
}
При удачной загрузке — выводится ссылка для скачивания изображения.
Темы:
1. QNetworkAccessManager последовательные запросы — C++ Qt
Литература:
1. Марк Саммерфилд «Qt Профессиональное программирование» (High tech) 2011г.