Russian Qt Forum

Qt => Работа с сетью => Тема начата: sobr_vamp от Июнь 17, 2011, 20:39



Название: загрузить html файл по ссылке
Отправлено: sobr_vamp от Июнь 17, 2011, 20:39
Обращаюсь к API яндекса, нахожу результаты.
Есть ссылка на страницу и сохранённая ссылка (на всякий пожарный =)

Нужен инстумент для сохранения html по ссылке на жесткий диск.
Направьте пожалуйста, куда копать и что лучше использовать.
Важен текст; картинки и остальную чепуху можно и, наверно, нужно не загружать.

Спасибо.


Название: Re: загрузить html файл по ссылке
Отправлено: kambala от Июнь 17, 2011, 21:17
я когда-то так делал, но не знаю насколько это правильно:
Код
C++ (Qt)
#ifndef PAGEDOWNLOADER_H
#define PAGEDOWNLOADER_H
 
#include <QtCore/QObject>
 
 
class QNetworkAccessManager;
class QNetworkReply;
 
class PageDownloader : public QObject
{
   Q_OBJECT
 
public:
explicit PageDownloader(QObject *parent = 0);
 
private slots:
void httpFinished(QNetworkReply *reply);
 
private:
QNetworkAccessManager *qnam;
};
 
#endif // PAGEDOWNLOADER_H
 
Код
C++ (Qt)
#include "pagedownloader.h"
 
#include <QtCore/QFile>
 
#include <QtNetwork/QNetworkRequest>
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkReply>
 
 
static const QString basePath = "http://my.website/";
 
PageDownloader::PageDownloader(QObject *parent) : QObject(parent)
{
qnam = new QNetworkAccessManager(this);
connect(qnam, SIGNAL(finished(QNetworkReply *)), SLOT(httpFinished(QNetworkReply *)));
 
qnam->get(QNetworkRequest(QUrl(basePath)));
}
 
void PageDownloader::httpFinished(QNetworkReply *reply)
{
QFile file("file.htm");
if (file.open(QIODevice::WriteOnly))
{
file.write(reply->readAll());
file.flush();
file.close();
}
 
reply->deleteLater();
reply = 0;
}
 


Название: Re: загрузить html файл по ссылке
Отправлено: sobr_vamp от Июнь 17, 2011, 21:39
Спасибо


Название: Re: загрузить html файл по ссылке
Отправлено: thechicho от Ноябрь 30, 2011, 16:48
а зачем
Код
C++ (Qt)
file.flush();

и
Код
C++ (Qt)
reply->deleteLater();
reply = 0;

у reply же предок qnam. т.е. раз qnam создается в куче, то удалять надо qnam?
или забить, удалится с выходом из приложения.
+ зачем к нулю присваивать? какая тут логика?

имхо, надо делать так:
.h
Код
C++ (Qt)
private:
QNetworkAccessManager qnam;
QNetworkReply *reply;

.cpp
Код
C++ (Qt)
PageDownloader::PageDownloader(QObject *parent) : QObject(parent)
{
reply = qnam.get(QNetworkRequst(QUrl(basePath)));
connect(reply, SIGNAL(finished()), this, SLOT(httpFinished()));
}
 
void PageDownloader::httpFinished()
{
   QFile file("file.htm");
   if (file.open(QIODevice::WriteOnly))
   {
file.write(reply->readAll());
//file.flush(); // нах?
file.close();
   }
 
   reply->deleteLater();
   //reply = 0; // тут я хз, надо или нет?
}


Название: Re: загрузить html файл по ссылке
Отправлено: kambala от Ноябрь 30, 2011, 17:24
а зачем
Код
C++ (Qt)
file.flush();
так данные явно сохраняются на диск. без этого мне приходилось ждать пока консольная программа завершится, чтобы файл записался (под виндой точно).
и
Код
C++ (Qt)
reply->deleteLater();
reply = 0;

у reply же предок qnam. т.е. раз qnam создается в куче, то удалять надо qnam?
или забить, удалится с выходом из приложения.
+ зачем к нулю присваивать? какая тут логика?
Цитировать
Note: After the request has finished, it is the responsibility of the user to delete the QNetworkReply object at an appropriate time. Do not directly delete it inside the slot connected to finished(). You can use the deleteLater() function.
а присваивание в 0 - на всякий случай


Название: Re: загрузить html файл по ссылке
Отправлено: thechicho от Ноябрь 30, 2011, 19:05
а почему file.write(reply->readAll());
сразу не записывает в файл?
write разве не синхронная функция?..

тогда, наверное, если все же использовать file.flush();
file.write(reply->readAll()); будет лишним.

QFile file("file.htm");
    if (file.open(QIODevice::WriteOnly))
    {
   file.flush();
   file.close();
    }


Название: Re: загрузить html файл по ссылке
Отправлено: kambala от Ноябрь 30, 2011, 19:22
тогда, наверное, если все же использовать file.flush();
file.write(reply->readAll()); будет лишним.
данные из воздуха не возьмутся. flush() "Flushes any buffered data to the file".


Название: Re: загрузить html файл по ссылке
Отправлено: thechicho от Ноябрь 30, 2011, 21:26
а точно
Код
C++ (Qt)
   QFile file("file.htm");
   if (file.open(QIODevice::WriteOnly))
   {
       reply->readAll();
       file.flush();
       file.close();
   }


Название: Re: загрузить html файл по ссылке
Отправлено: kambala от Ноябрь 30, 2011, 22:22
а записывать кто данные будет в файл - Пушкин?


Название: Re: загрузить html файл по ссылке
Отправлено: BRE от Ноябрь 30, 2011, 22:36
Я не знаю, что вы обсуждаете, но закрытие файла автоматически делает flush. :)
Кстати, при разрушении QFile файл автоматически будет закрыт (соответственно с flush).
Достаточно такого:
Код
C++ (Qt)
{
   QFile file("file.htm");
   if (file.open(QIODevice::WriteOnly))
file.write(reply->readAll());
} // Здесь будет вызван деструктор QFile, который закроет файл (close) при этом все буферы вытолкнутся на диск (flush)
 


Название: Re: загрузить html файл по ссылке
Отправлено: thechicho от Ноябрь 30, 2011, 23:03
дак,
reply->readAll(); - запишет данные в буфер.
file.flush(); - запишет из буфера в файл.
так ведь?)
BRE,
kambala сказал, что "так данные явно сохраняются на диск. без этого мне приходилось ждать пока консольная программа завершится, чтобы файл записался (под виндой точно)".
поэтому не канает, твой вариант, т.к. по словам kambala, данные запишутся только после выхода из консоли, а нам тип надо, чтобы сразу записались :)
kambala, твой никнейм склонять можно?)


Название: Re: загрузить html файл по ссылке
Отправлено: thechicho от Ноябрь 30, 2011, 23:06
Код
C++ (Qt)
   reply->readAll();
   QFile file("file.htm");
   if (file.open(QIODevice::WriteOnly))
   {        
       file.flush();
   }

ы


Название: Re: загрузить html файл по ссылке
Отправлено: kambala от Ноябрь 30, 2011, 23:06
Я не знаю, что вы обсуждаете, но закрытие файла автоматически делает flush. :)
ну у меня почему-то файл не записывался сразу, а только по завершении консольного приложения (в main() я просто создавал объект типа PageDownloader и вызывал app.exec()), потому я доставил flush() - хуже-то точно не будет от него :)
дак,
reply->readAll(); - запишет данные в буфер.
file.flush(); - запишет из буфера в файл.
ну так в QFile и находится буфер, а readAll() возвращает байт-массив, который надо куда-то (в наш буфер) записать
kambala, твой никнейм склонять можно?)
можно


Название: Re: загрузить html файл по ссылке
Отправлено: thechicho от Ноябрь 30, 2011, 23:10
// ну так в QFile и находится буфер, а readAll() возвращает байт-массив, который надо куда-то (в наш буфер) записать
ааа
ну тогда, ты прав :)
flush(); юзаем, если необходима мгновенная запись из консоли


Название: Re: загрузить html файл по ссылке
Отправлено: BRE от Ноябрь 30, 2011, 23:12
ну у меня почему-то файл не записывался сразу, а только по завершении консольного приложения (в main() я просто создавал объект типа PageDownloader и вызывал app.exec()), потому я доставил flush() - хуже-то точно не будет от него :)
Возможно время жизни объекта QFile было равно жизни программы.
Сейчас же время жизни ограничивается слотом httpFinished.
А хуже конечно не будет. :)


Название: Re: загрузить html файл по ссылке
Отправлено: nekitozzz от Декабрь 12, 2011, 21:38
Тоже интересует эта тема, не могу понять, зачем у меня при запуске программа даже в httpFinished не заходит  :(

Код
C++ (Qt)
#include <QtGui/QApplication>
#include "qmlapplicationviewer.h"
#include "get_html.h"
 
int main(int argc, char *argv[])
{
   QApplication app(argc, argv);
   PageDownloader html();
   QmlApplicationViewer viewer;
   viewer.setOrientation(QmlApplicationViewer::ScreenOrientationAuto);
   viewer.setMainQmlFile(QLatin1String("qml/torrent_reminder/main.qml"));
   viewer.showExpanded();
 
   return app.exec();
}
 

Код
C++ (Qt)
#ifndef GET_HTML_H
#define GET_HTML_H
#include <QtCore/QObject>
class QNetworkAccessManager;
class QNetworkReply;
class PageDownloader : public QObject
{
   Q_OBJECT
public:
   explicit PageDownloader(QObject *parent = 0);
private slots:
       void httpFinished(QNetworkReply *reply);
private:
   QNetworkAccessManager *manager;
   // QString get_code();
};
#endif // GET_HTML_H
 

Код
C++ (Qt)
#include <QtCore/QFile>
 
#include <QtNetwork/QNetworkRequest>
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkReply>
#include "get_html.h"
 
static const QString basePath = "http://www.prog.org.ru/topic_18530_0.html";
 
PageDownloader::PageDownloader(QObject *parent): QObject(parent)
{
      manager = new QNetworkAccessManager(this);
      connect(manager, SIGNAL(finished(QNetworkReply *)),
              this, SLOT(httpFinished(QNetworkReply *)));
      manager->get(QNetworkRequest(QUrl(basePath)));
}
 
void PageDownloader::httpFinished(QNetworkReply *reply)
{
       QFile file("file.htm");
       if (file.open(QIODevice::WriteOnly))
       {
               file.write(reply->readAll());
               file.flush();
       }
       reply->deleteLater();
       reply = 0;
}