Um mit dem Netzwerk zu arbeiten, können Sie zusätzlich zur Verwendung der Klassen QTcpSocket oder QUdpSocket QNetworkAccessManager verwenden. Diese Klasse bietet Funktionen zum Senden von Anforderungen über das Netzwerk und Empfangen von Antworten und ist praktisch für mit dem HTTP-Protokoll arbeiten.
Daher schlage ich vor, eine Anwendung zu schreiben, mit der Sie eine XML-Datei von der Site herunterladen und ihre Datei auf die lokale Festplatte Ihres Computers schreiben können.
Die Anwendungslogik ist wie folgt:
- Laden Sie die Datei herunter;
- Schreiben Sie es mit dem folgenden Pfad auf eine lokale Festplatte C: /example/file.xml;
- Lesen Sie die geschriebene Datei und zeigen Sie die Daten in QTextEdit an.
Projektstruktur für die Arbeit mit HTTP
Der Aufbau des Projekts sieht wie folgt aus:
- DownloadHttp.pro - Projektprofil;
- main.cpp - Quellcodedatei der Hauptanwendung;
- widget.h - Header-Datei des Anwendungsfensters;
- widget.cpp - Datei mit Quellcodes des Anwendungsfensters;
- downloader.h - Klassen-Header-Datei zum Herunterladen der Datei;
- doqnloader.cpp - Datei mit den Quellcodes der Klasse zum Herunterladen der Datei.
DownloadHttp.pro und main.cpp
main.cpp wird standardmäßig erstellt und nicht geändert, während Sie in der Datei DownloadHttp.pro das Netzwerkmodul enthalten müssen.
#------------------------------------------------- # # Project created by QtCreator 2015-12-13T21:02:32 # #------------------------------------------------- QT += core gui network greaterThan(QT_MAJOR_VERSION, 4): QT += widgets TARGET = DownloadHttp TEMPLATE = app SOURCES += main.cpp\ widget.cpp \ downloader.cpp HEADERS += widget.h \ downloader.h FORMS += widget.ui
widget.ui
Im Anwendungsfenster gibt es eine Schaltfläche, durch die das Herunterladen von Daten von der Site gestartet wird, und QTextEdit, in das die Daten aus der gespeicherten Datei eingefügt werden.
widget.h
Header-Datei des Anwendungsfensters. Darin enthalten wir die Header-Datei der Klasse Downloader , die für das Herunterladen von Daten von der Site und das Speichern in einer Datei verantwortlich ist. Selbstverständlich deklarieren wir ein Objekt dieser Klasse Downloader Am Ende des Downloads wird auch die Signatur des Slots zum Auslesen von Daten aus einer gespeicherten Datei deklariert.
#ifndef WIDGET_H #define WIDGET_H #include <QWidget> #include <QFile> #include <downloader.h> namespace Ui { class Widget; } class Widget : public QWidget { Q_OBJECT public: explicit Widget(QWidget *parent = 0); ~Widget(); private slots: void readFile(); private: Ui::Widget *ui; Downloader *downloader; // Объявляем объект класса для скачивания данных по http }; #endif // WIDGET_H
widget.cpp
Es gibt zwei Signalverbindungen zu Slots in den Quellcodes. Eine Verbindung ist für die Verarbeitung des Schaltflächenklicks verantwortlich und die zweite für das Lesen der Daten aus der Datei beim Herunterladen der Datei.
#include "widget.h" #include "ui_widget.h" Widget::Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Widget) { ui->setupUi(this); downloader = new Downloader(); // Инициализируем Downloader // по нажатию кнопки запускаем получение данных по http connect(ui->pushButton, &QPushButton::clicked, downloader, &Downloader::getData); // по окончанию получения данных считываем данные из файл connect(downloader, &Downloader::onReady, this, &Widget::readFile); } Widget::~Widget() { delete ui; } void Widget::readFile() { QFile file("C:/example/file.xml"); if (!file.open(QIODevice::ReadOnly)) // Открваем файл, если это возможно return; // если открытие файла невозможно, выходим из слота // в противном случае считываем данные и устанавилваем их в textEdit ui->textEdit->setText(file.readAll()); }
donwloader.h
Und jetzt die Header-Datei des Helden des Anlasses. Darin deklarieren wir eine Instanz der Klasse QNetworkAccesManager sowie Methoden zum Initialisieren einer Anforderung an die Site über ihre URL und zum Verarbeiten der empfangenen Antwort.
#ifndef DOWNLOADER_H #define DOWNLOADER_H #include <QObject> #include <QNetworkAccessManager> #include <QNetworkRequest> #include <QNetworkReply> #include <QFile> #include <QUrl> #include <QDebug> class Downloader : public QObject { Q_OBJECT public: explicit Downloader(QObject *parent = 0); signals: void onReady(); public slots: void getData(); // Метод инициализации запроса на получение данных void onResult(QNetworkReply *reply); // Слот обработки ответа о полученных данных private: QNetworkAccessManager *manager; // менеджер сетевого доступа }; #endif // DOWNLOADER_H
downloader.cpp
ACHTUNG!!! - Prüfen Sie vor dem Start der Anwendung die Verfügbarkeit der URL aus dem Beispiel, um nicht mit dem Kopf gegen die Wand zu schlagen, wenn die Site einfach nicht erreichbar ist. Besser noch, ersetzen Sie es durch die URL, die Sie erreichen möchten. Und es kann auch sinnvoll sein, die Dateierweiterung auf txt zu ändern.
#include "downloader.h" Downloader::Downloader(QObject *parent) : QObject(parent) { // Инициализируем менеджер ... manager = new QNetworkAccessManager(); // ... и подключаем сигнал о завершении получения данных к обработчику полученного ответа connect(manager, &QNetworkAccessManager::finished, this, &Downloader::onResult); } void Downloader::getData() { QUrl url("http://www.mtbank.by/currxml.php"); // URL, к которому будем получать данные QNetworkRequest request; // Отправляемый запрос request.setUrl(url); // Устанавлвиваем URL в запрос manager->get(request); // Выполняем запрос } void Downloader::onResult(QNetworkReply *reply) { // Если в процесе получения данных произошла ошибка if(reply->error()){ // Сообщаем об этом и показываем информацию об ошибках qDebug() << "ERROR"; qDebug() << reply->errorString(); } else { // В противном случае создаём объект для работы с файлом QFile *file = new QFile("C:/example/file.xml"); // Создаём файл или открываем его на перезапись ... if(file->open(QFile::WriteOnly)){ file->write(reply->readAll()); // ... и записываем всю информацию со страницы в файл file->close(); // закрываем файл qDebug() << "Downloading is completed"; emit onReady(); // Посылаем сигнал о завершении получения файла } } }
Ergebnis
Als Ergebnis erhalten Sie eine Anwendung, die Daten von der Site-Seite entfernt und in QTextEdit anzeigt, wie in der folgenden Abbildung gezeigt. Eine Demonstration der Anwendung finden Sie im Video-Tutorial.
Link zum Download des Projekts in einem Zip-Archiv: downloadhttp.zip
Здравствуйте! Когда тестировал ваш проект в режиме Debug выводит такую ошибку:
после закрытия программы. Также и с моим проектом. Я искал ошибку и нашел ошибку вот в этой строке: manager = new QNetworkAccessManager(); Также и у меня когда создаю обект класса QNetworkAccessManager. В чем пожет быть проблема? Спасибо.Здравствуйте! Не знаю. На всякий случай я скачал проект и проверил сейчас у себя его работу, но никаких исключений не выкидывает. Проверял на Qt 5.8 GCC 64 bit под Ubuntu 16.04. Проект работает стабильно.
Какой версией Qt пользуетесь?
Я использую Qt 5.7.1 с Microsoft Visual Studio 2015 (Windows 10) и на Qt 5.9.0 Beta 2 также. У меня мой и ваш проект работает стабильно, но если через Debug тестировать и закрыть программу то такая ошибка появляется. Пробовал через Visual Studio 2015 отлаживать, но выводит ошибку:
Или иногда эту ошибку: После выводит код ассемблера: К примеру на Windows 8.1 x64 тестировал то такую ошибку выводит как предупреждение: -1: error: Exception at 0x74f3b782, code: 0xd: , flags=0x1 (execution cannot be continued) (first chance) А на Windows 10 как ошибку. Не могу точно найти где ошибка, но если закоментировать код инициализации QNetworkAccessManager: manager = new QNetworkAccessManager(); тогда ошибки нет и соотвественно не работает подключение сети в программе.Не похоже, чтобы это была проблема с Qt или ошибкой в коде. У меня такой проблемы как у вас не возникает. Проверил на следующем:
Исключения по окончании работы не выбрасываются. У вас фигурирует в исключениях KernelBase.dll . Скорее всего это или придурь компилятора или сама библиотека кривая.
Но для очистки совести могу посоветовать передать указатель на parent объект при создании объекта QNetworkAccessManager
Да, и если указать parent (manager = new QNetworkAccessManager(this);) также ошибка. Я вот что еще заметил когда тестировал на Visual Studio 2015, Thread: [1328]wlanapi.dll!_NotificationApcThreadProc@4, то есть ошибка/сбой программы в этой функции, но у меня нет подключения к wlanapi (библиотеки WiFi) в программе, значит ошибка происходит только на Windows 10 и с библиотекой Qt (Qt5Networkd.dll/Qt5Network.dll).
Считаю, что библиотека Qt Network работает нормально. Дело в том, что данная библиотека перебирает все возможные варианты подключений, в том числе и wi-fi подключения, когда пытается найти выход в интернет. Мне думается, что тут исключительно локальная проблема с системными библиотеками на Windows 10.
Евгений, спасибо за полезную статью. Немного отредактировал добавленные к уроку файлы, чтобы запустить программу на версии фреймворма Qt 5.10.
DownloadHttp.zip
Вам спасибо за дополнение.
А вот как выгрузить файл на сервер по http протоколу? Допустим на regRu. И как получить путь файла, которой отображается в файловом менеджере regRu, чтобы загрузить его.
Не реализовывал такое, так что пока не подскажу. Если будет такой опыт, то напишу статью.
Как произвести загрузку используя HTTPS протокол?
точно так же как и http. Просто url адрес будет с https.
Здравствуйте! Подскажите, пожалуйста, как сделать так, чтобы программа срабатыала без нажатия кнопки? Ну чисто при загрузке формы... Я так понимаю, надо что-то поменять в этой строчке
Но вот что именно? Если не сложно, свяжитесь со мной. А то я спать спокойно не смогу пока не выясню как это делается.
Попробуйте просто вызвать метод getData в конструкторе класса
Добрый день.
Изучаю Qt на ваших уроках. Всё нормально работает на Linux. А под Win один раз запустилось, а сейчас вместо данных сайта получается ошибк "Unable to write". Куда копать, ума не приложу.
Кто подскажет, буду благдарен.