LinuxForum.Fans
Тема

Как скачать файл из проекта на Qt

Автор: XRevan86 46 сообщений 12209 просмотров
#109690
voral написал:
Поясните.

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

#109696
drBatty написал:

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

Тогда понятно.... Я думал вы про язык.

#109698
voral написал:
Тогда понятно.... Я думал вы про язык.

компилятору плевать на пробелы. в любом известном мне ЯП кроме python'а.
а сишному даже на CR плевать. Вот только это не значит, что нужно так этим пользоваться. Классики пишут, что пробел - лучший комментарий.

#109705
drBatty написал:

компилятору плевать на пробелы. в любом известном мне ЯП кроме python'а.
а сишному даже на CR плевать. Вот только это не значит, что нужно так этим пользоваться. Классики пишут, что пробел - лучший комментарий.

Однако, топикастер не просил оценить его код (Подозреваю он просто коипастил как есть из разных участков кода). Поэтому достаточно, имхо, было просто посоветовать придерживаться правил оформления кода. (только не ребусами)
Ну да ладно, предлагаю приостновить это отклонение от темы.

#109713
voral написал:
имхо, было просто посоветовать придерживаться правил оформления кода. (только не ребусами)

лучше-бы ТС почитал man connect, и ознакомился с примером в man addrinfo. И Qt тут не причём.

#110695

voral
drBatty (в IRC)

Спасибо большое, Вы меня приблизили к цели smile.

Однако, файл не загружается...

text
#include <iostream>
#include <cstdlib>
#include <string>
#include <QtCore>
#include <QApplication>
#include <QDir>
#include <QtNetwork>
#include <QNetworkAccessManager>
#include <QUrl>

QString PChar2String(const char* PChar); char* String2PChar(const QString String); int URLDownloadToFile(const QString URL, const QString FileName);

QString CD = PChar2String("");

int main(int ParamCount, char* ParamStr[]) { QApplication Application(ParamCount, ParamStr); CD = Application.applicationDirPath(); URLDownloadToFile(PChar2String("http://linuxforum.ru/img/linuxforum_winter.jpg"), PChar2String("/home/user/Documents/linuxforum_winter.jpg")); return 0; }

QString PChar2String(const char* PChar) { return QString("%1").arg(PChar); }

char* String2PChar(const QString String) { QByteArray Result = String.toAscii(); return Result.data(); }

int URLDownloadToFile(const QString URL, const QString FileName) { QNetworkAccessManager qnam; QNetworkReply* Reply = NULL; QFile* File = NULL; if (FileName.isEmpty()) return 1; if (QFile::exists(FileName)) QFile::remove(FileName); File = new QFile(FileName); if ( !File->open(QIODevice::WriteOnly) ) { delete File; File->remove(); return 1; } Reply = qnam.get(QNetworkRequest(QUrl(URL))); if (Reply->error()) { delete File; File->remove(); return 1; } File->flush(); if ( File ) File->write(Reply->readAll()); File->close(); delete Reply; delete File; return 0; }

(создаётся пустой файл)...

#110772
Darth Revan написал:
text

    delete File;
    File = 0;
    if (File)
        File->write(Reply->readAll());
    return 0;
}

(создаётся пустой файл)...

Может я и туплю. Но вы прибили объект. Указатель заганли в 0.... С первой поптки можно угадать что условие у вас ни когда не выполняется.
А еще чуть выше вы сказали что вам и реплай уже не нужен.... Т.е. если всетаки выполнить условие. То не факт что еще будет жив объект реплай.
Вообще говоря. Мне кажется закинуть все в одну процедуру. Не есть гуд. Я правда не пробовал, но мне кажется. Тут работать будет но не стабильно.
Чем вам не приглянулся мой (а точнее из КуТе Асситента) пример? он должен работать.

#110915

voral написал:
Я правда не пробовал, но мне кажется - тут работать будет, но нестабильно.
voral написал:
тут работать будет
Прошу рассказать - как сделать рабочим.
#110991

Darth Revan,
Комментарии следующие:
Во первых, почитай документацию по Qt (или оригинал в Qt Assistant'е)
Во вторых, почитай конкретно раздел про QNAM.

Насколько я понимаю его устройство, фиг ты сделаешь без классов адекватную качалку. Вообще с Qt4 работать избегая классов - кощунство и глупость.

В приведенном тобой коде главная твоя ошибка состоит в том, что ты не дожидаешься завершения запроса. У QNetworkReply есть функция isFinished(). Сделай хотя бы ожидание окончания запроса. А потом уже обрабатывай ошибки.

Во вторых, подключи хедер QtDebug и пользуйся замечательной штукой qDebug() для вывода отладочной информации.

Рассмотрим кусок кода:

text

    if (Reply->error())
    {
        delete File;
        File->remove();
        return 1;
    }

Тут вообще странная штука. Ты удаляешь объект File(!) а потом ещё вызываешь remove у уже удаленного объекта. Что из этого выйдет?
Также обрати внимание на то, что у большинства объектов в Qt есть функция deleteLater(), которой и стоит пользоваться вместо delete Object;

Кстати именно в этот кусок и стоит воткнуть вывод сообщений об ошибке:

text

    if (Reply->error())
    {
        qDebug()<<"An error has occured: "<<Reply->errorString();
        File->remove();
        File->deleteLater();
        return 1;
    }

Вот как-то так для начала.

И перепиши на классах. Код станет чище, его станет проще поддерживать в будущем и в целом логичнее и понятнее.

P.S. Вообще лучший способ не править код из поста, а воспользоваться кодом voral'а. Разобраться сначала в нем, а потом уже свой вариант реализации сделать. Так будет правильнее.

#110992
Darth Revan написал:
Прошу рассказать - как сделать рабочим.

что сделать? Ваш вариант?

Мой рабочий... Только что скомпилил и залил первую страницу форума...
Хотя я вам не дал pro файл

text

HEADERS += HttpDownload.h
SOURCES += HttpDownload.cpp \
           main.cpp
QT += network
#112011

Всё, я перехожу на ООП.
Ещё раз спасибо voral и Civil smile. Желаю вам много радости и конца света в Новом Году!

voral
Да... в Вашем коде 0 Бит получается :D.

#112086
Darth Revan написал:
Всё, я перехожу на ООП.
Ещё раз спасибо voral и Civil smile. Желаю вам много радости и конца света в Новом Году!

voral
Да... в Вашем коде 0 Бит получается :D.

странно у меня скачалась вся страниуа

#113055

main.cpp:

text
#include <iostream>
#include <cstdlib>
#include <string>
#include <QApplication>
#include <QDir>

#include "functions.h"

QString CD = PChar2QString("");

int main(int ParamCount, char* ParamStr[]) { QApplication Application(ParamCount, ParamStr); QURLDownloadToFile DownloadFile; QConfigFile ConfigFile; CD = Application.applicationDirPath(); ConfigFile.Save(CD + QDir::separator() + PChar2QString("hello.ini"), PChar2QString("Main"), PChar2QString("DefaultValue"), PChar2QString("HelloWorld")); DownloadFile.Initial(PChar2QString("http://www.google.ru/images/srpr/nav_logo27.png"), PChar2QString("google.png")); return 0; }

functions.cpp:

text
#include <QtCore>
#include <QObject>
#include <QDir>
#include <QtNetwork>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QUrl>

#include "functions.h"

QString PChar2QString(const char* PChar) { return QString("%1").arg(PChar); }

char* QString2PChar(const QString String) { QByteArray Result = String.toAscii(); return Result.data(); }

QURLDownloadToFile::QURLDownloadToFile(QObject* parent): QObject(parent) { }

void QURLDownloadToFile::startRequest(QUrl URL) { Reply = qnam.get(QNetworkRequest(URL)); connect(Reply, SIGNAL(finished()), this, SLOT(httpFinished())); connect(Reply, SIGNAL(readyRead()), this, SLOT(httpReadyRead())); }

void QURLDownloadToFile::Initial(QString StringURL, QString FileName) { URL.setUrl(StringURL); if ( FileName == PChar2QString("") ) { QFileInfo fileInfo(URL.path()); FileName = fileInfo.fileName(); } if ( QFile::exists(FileName) ) { File->remove(); }

File = new QFile(FileName); if ( !File->open(QIODevice::WriteOnly) ) { delete File; File = 0; return; } httpRequestAborted = false; startRequest(URL); }

void QURLDownloadToFile::httpFinished() { File->flush(); File->close(); Reply->deleteLater(); Reply = 0; delete File; File = 0; }

void QURLDownloadToFile::httpReadyRead() { if ( File ) File->write( Reply->readAll() ); }

QConfigFile::QConfigFile(QObject *parent): QObject(parent) { }

QString QConfigFile::Read(const QString FileName, const QString Section, const QString Value, const QString Default) { IniFile = FileName; QSettings Settings(IniFile, QSettings::IniFormat); Settings.beginGroup(Section); Result = Settings.value(Value, "").toString(); if ( Result == "" ) Result = Default; Settings.endGroup(); return Result; }

void QConfigFile::Save(const QString FileName, const QString Section, const QString Value, const QString InValue) { IniFile = FileName; QSettings Settings(IniFile, QSettings::IniFormat); Settings.beginGroup(Section); Settings.setValue(Value, InValue); Settings.endGroup(); }

functions.h:

text
#ifndef FUNCTIONS_H
#define FUNCTIONS_H

#include <QObject> #include <QNetworkAccessManager> #include <QUrl>

QString PChar2QString(const char* PChar); char* QString2PChar(const QString String);

QT_BEGIN_NAMESPACE class QFile; class QNetworkReply; class QNetworkRequest; QT_END_NAMESPACE

class QURLDownloadToFile: public QObject { Q_OBJECT

public: QURLDownloadToFile(QObject* parent = 0); void Initial(QString StringURL, QString FileName);

private slots: void startRequest(QUrl URL); void httpFinished(); void httpReadyRead();

private: QUrl URL; QNetworkAccessManager qnam; QNetworkReply* Reply; QFile* File; int httpGetId; bool httpRequestAborted; };

class QConfigFile: public QObject { Q_OBJECT

public: QConfigFile(QObject* parent = 0); QString Read(const QString FileName, const QString Section, const QString Value, const QString Default); void Save(const QString FileName, const QString Section, const QString Value, const QString InValue);

private: QString Result; QString IniFile; };

#endif

Файл пустой.

#117040

Помогите, пожалуйста.
(это своеобразный "UP").

#117056

Все просто.
1. Ошибка

text

if ( QFile::exists(FileName) )
{
      File->remove();
}

меняем на

text

if ( QFile::exists(FileName) )
{
      File->remove(FileName);
}

2. Ошибка и главная

Сколько живет ваш объект? ;) А ни сколько доли секунды. Соответственно ни чего не успевает принять. Достаточно в конце main.cpp сделать так

text

....
    QDialog dlg;
    dlg.exec();
    return 0;
}

И вы получите свою картнку (Только окно не закрывайте моментально после открытия в данном примере это лишь костыль для создания задержки)

#117059

Т.е. вам нужно дать время программе скачать нужный файл. Как это сделать зависит от вашего проекта и задачи.

#117320

voral
А без этого костыля можно как-нибудь?

#117350
Darth Revan написал:
voral
А без этого костыля можно как-нибудь?

Вместо

text
return 0;

Сделайте

text
return app.exec();

Где app - экземпляр QApplication.

#117363

А ещё установите qt4-doc-html, там есть /usr/share/qt4/doc/html/index.html,
в нём Tutorials and Examples, в Examples есть Network, в Network есть Download,
это именно то, что вы пытаетесь сделать. Там в main тоже

text
return  app.exec();

это стандартный спсоб запуска Qt-программ.

Конечно, можно заканчивать програму изнутри и сразу после окончания
скачивания файла вызовом

text
this->close();

кажется, так, сам давно уже в Qt ничего не делал.

Пётр.

#117421
Peter написал:

это именно то, что вы пытаетесь сделать. Там в main тоже
text
return  app.exec();

это стандартный спсоб запуска Qt-программ.

Это способ запуска цикла обработки сообщений, который будет выполнятся до вызова функций quit() или exit(). Не надо никаких форм, просто в классе который скачивает файл надо создать сигнал downloadFinished() и сделать приблизительно следующее:

text
QApplication app(argc, argv);
MyOwnDownloader downloader;

downloader.connect(&downloader, SIGNAL(downloadFinished()), &app, SLOT(quit()));

/* тут начинаем качать файл */

return app.exec();

Как-то так.

Войдите или зарегистрируйтесь, чтобы ответить.