MyTetra Share
Делитесь знаниями!
Как работать с QNetworkAccessManager
Время создания: 20.03.2016 22:41
Текстовые метки: Qt, QNetworkAccessManager, сеть
Раздел: Компьютер - Программирование - Язык C++ (Си++) - Библиотека Qt - Работа с сетью
Запись: xintrea/mytetra_syncro/master/base/1453285930b64f49g408/text.html на raw.github.com

Работа с 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г.


 
MyTetra Share v.0.59
Яндекс индекс цитирования