1

Я начинающий [size=1]быдло[/size]кодер на Qt.
Ищу компонент, который тупо скачивает файл.
Наращиваю базу функций для своих [size=1]быдло[/size]проектов smile.

2

не совсем понятно, что вам надо. что значит "тупо скачивает файл"? по ссылке скачивает или как?

3

LifeIsMusic
Ну да.
DownloadFile(QUrl, QString) smile.

4

Darth Revan пишет:

LifeIsMusic
Ну да.
DownloadFile(QUrl, QString) smile.

Ну совсе "тупо" не получится.

QNetworkAccessManager

Устаревшие:
QHttp
QFtp

Среди примеров идущих с Qt есть "FTP Client" и "HTTP Client"

То что не убивает нас, делает нас сильнее! © Ницше.
When life puts you in tough situations, don’t say "why me". Just say "try me".
GNU/Linux Debian

5 (26.12.2010 17:54:13 отредактировано XRevan86)

Qt пишет:

int URLDownloadToFile(const QString URL, const QString FileName)
{
    QFileInfo fileInfo(URL);
    QNetworkAccessManager qnam;
    QNetworkReply* reply;
    QString connect;
    if ( FileName.isEmpty() )
      return 1;
    QFile::remove(FileName);
    QFile* File = new QFile(FileName);
    if ( !File->open(QIODevice::WriteOnly) )
    {
        delete File;
        File = 0;
        return 1;
    }
    reply = qnam.get(QNetworkRequest(URL));
        connect(reply, SIGNAL(finished()),
            this, SLOT(httpFinished()));
        connect(reply, SIGNAL(readyRead()),
            this, SLOT(httpReadyRead()));
        connect(reply, SIGNAL(downloadProgress(qint64,qint64)),
            this, SLOT(updateDataReadProgress(qint64,qint64)));
    }

g++ пишет:

error: invalid use of ‘this’ in non-member function

Моя попытка написать простую, как пень, функцию скачивания файла провалилась.

6

простите, а почему не fopen() ?

Карусель разнесло по цепочке за час
Всех известий — конец
Да, весна началась!
(всё к лицу подлецу, как родному отцу, не рассказывай, батя, и так всё пройдёт)

7 (22.12.2010 18:44:30 отредактировано voral)

Darth Revan пишет:

int URLDownloadToFile(const QString URL, const QString FileName)

Естественно. this указатель на экземляр класса. Следовательно это код метода, какого то класса. Но тогда должно начинаться примерно так:

int YourClassName::URLDownloadToFile(const QString URL, const QString FileName)

А так же среди методов этого класса должны быть слоты updateDataReadProgress, httpReadyRead и httpFinished.

То что не убивает нас, делает нас сильнее! © Ницше.
When life puts you in tough situations, don’t say "why me". Just say "try me".
GNU/Linux Debian

8

Darth Revan пишет:

connect(reply, SIGNAL(finished()),
                    this, SLOT(httpFinished()));

чё-то нипрапарсил....
скобки-же вы закрыли КЕМ! после finished. ДВЕ ШТУКИ! вот компилятор и ругается.

Карусель разнесло по цепочке за час
Всех известий — конец
Да, весна началась!
(всё к лицу подлецу, как родному отцу, не рассказывай, батя, и так всё пройдёт)

9

drBatty пишет:

простите, а почему не fopen() ?

Да и и это здесь не нужно. Засунуть имя файла в QFileInfo. Этот класс и ответит доступен ли он для записи. Здесь этот опен только для этого и нужен - если записать нельзя то и файл не скачивается

То что не убивает нас, делает нас сильнее! © Ницше.
When life puts you in tough situations, don’t say "why me". Just say "try me".
GNU/Linux Debian

10

drBatty пишет:

чё-то нипрапарсил....
скобки-же вы закрыли КЕМ! после finished. ДВЕ ШТУКИ! вот компилятор и ругается.

Со скобками на мой взгляд все ок

То что не убивает нас, делает нас сильнее! © Ницше.
When life puts you in tough situations, don’t say "why me". Just say "try me".
GNU/Linux Debian

11 (22.12.2010 18:57:17 отредактировано voral)

С QFile* File здесь какаято фигня. Мы его пытаемся открыть только для записи. Создаем объект здесь. Сслка на объект в этом методе.
Когда начинается закачка файла. То как мы можем получить ссылку на открытый файл...... Запись то в файл идет в слоте httpReadyRead

Здается код исправлен и в исходном варианте File является свойство класса.

То что не убивает нас, делает нас сильнее! © Ницше.
When life puts you in tough situations, don’t say "why me". Just say "try me".
GNU/Linux Debian

12

voral пишет:

Со скобками на мой взгляд все ок

ну то на ваш. а я с компилятором негодуем.

Карусель разнесло по цепочке за час
Всех известий — конец
Да, весна началась!
(всё к лицу подлецу, как родному отцу, не рассказывай, батя, и так всё пройдёт)

13

drBatty пишет:

ну то на ваш. а я с компилятором негодуем.

Вы с компилятором не внимательны bx После ваших слов я даже вставил этот кусок в проект. Здесь все Ок.
Ошибка явная и думать не надо. Приведенный выше листинг это листинг функции, а не метода класса. Соответственно нет ни какого this.

Топикасетр, я глянул Вы взяли пример HTTP Client и попытались его выкусить. Не пытайтесь сделать отдельную функцию. Просто возмите этот класс и выкиньте все что не нужно. Начиная с наследия от QDialog

То что не убивает нас, делает нас сильнее! © Ницше.
When life puts you in tough situations, don’t say "why me". Just say "try me".
GNU/Linux Debian

14 (22.12.2010 19:39:15 отредактировано voral)

Не проверял но примерно так:
HttpDownload.h

#ifndef HttpDownload_H
#define HttpDownload_H

#include <QNetworkAccessManager>
#include <QUrl>

QT_BEGIN_NAMESPACE
class QFile;
class QNetworkReply;
QT_END_NAMESPACE

class HttpDownload : public QObject
{
    Q_OBJECT

public:
    HttpDownload(QObject *parent = 0);
    void downloadFile(QUrl url);

private slots:
    void startRequest(QUrl url);
    void cancelDownload();
    void httpFinished();
    void httpReadyRead();
    void updateDataReadProgress(qint64 bytesRead, qint64 totalBytes);

private:
    QUrl url;
    QNetworkAccessManager qnam;
    QNetworkReply *reply;
    QFile *file;
    int httpGetId;
    bool httpRequestAborted;
};

#endif

HttpDownload.cpp

#include <QtNetwork>

#include "HttpDownload.h"

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

void HttpDownload::startRequest(QUrl url)
{
    reply = qnam.get(QNetworkRequest(url));
    connect(reply, SIGNAL(finished()),
            this, SLOT(httpFinished()));
    connect(reply, SIGNAL(readyRead()),
            this, SLOT(httpReadyRead()));
    connect(reply, SIGNAL(downloadProgress(qint64,qint64)),
            this, SLOT(updateDataReadProgress(qint64,qint64)));
}

void HttpDownload::downloadFile(QUrl url)
{
    QFileInfo fileInfo(url.path());
    QString fileName = fileInfo.fileName();
    if (QFile::exists(fileName)) {
//        обработка ситуации если файл уже есть
    }

    file = new QFile(fileName);
    if (!file->open(QIODevice::WriteOnly)) {
// если файл нельза записать
        delete file;
        file = 0;
        return;
    }
    httpRequestAborted = false;
    startRequest(url);
}

void HttpDownload::cancelDownload()
{
    httpRequestAborted = true;
    reply->abort();
}

void HttpDownload::httpFinished()
{
    if (httpRequestAborted) {
        if (file) {
            file->close();
            file->remove();
            delete file;
            file = 0;
        }
        reply->deleteLater();
        return;
    }
    file->flush();
    file->close();
    reply->deleteLater();
    reply = 0;
    delete file;
    file = 0;
}

void HttpDownload::httpReadyRead()
{
    if (file)
        file->write(reply->readAll());
}

void HttpDownload::updateDataReadProgress(qint64 bytesRead, qint64 totalBytes)
{
    if (httpRequestAborted)
        return;
// если нужно информируем о прогрессе
}

создаешь объект этого класса. Вызываешь downloadFile(QUrl url). Прервать можно вызвав cancelDownload()

До кучи тестовый main.cpp

 #include <QApplication>
#include <QDialog>
#include "HttpDownload.h"

int main(int argc, char *argv[])
{
     QApplication app(argc, argv);
    HttpDownload httpDownload;
    httpDownload.downloadFile(QUrl("http://linuxforum.ru/index.php"));
    QDialog dlg;
    dlg.show();
    return dlg.exec();
}
То что не убивает нас, делает нас сильнее! © Ницше.
When life puts you in tough situations, don’t say "why me". Just say "try me".
GNU/Linux Debian

15

voral пишет:

Вы с компилятором не внимательны wink После ваших слов я даже вставил этот кусок в проект. Здесь все Ок.
Ошибка явная и думать не надо. Приведенный выше листинг это листинг функции, а не метода класса. Соответственно нет ни какого this.

ничегонипонял.

      reply = qnam.get(QNetworkRequest(URL));
            connect(reply, SIGNAL(finished()),
                    this, SLOT(httpFinished()));
            connect(reply, SIGNAL(readyRead()),
                    this, SLOT(httpReadyRead()));
            connect(reply, SIGNAL(downloadProgress(qint64,qint64)),
                    this, SLOT(updateDataReadProgress(qint64,qint64)));

это вообще, на каком языке? пайтон что-ли?

Карусель разнесло по цепочке за час
Всех известий — конец
Да, весна началась!
(всё к лицу подлецу, как родному отцу, не рассказывай, батя, и так всё пройдёт)

16

это с++ ag

17

odin, нет.
это быдлокод. извините.

Карусель разнесло по цепочке за час
Всех известий — конец
Да, весна началась!
(всё к лицу подлецу, как родному отцу, не рассказывай, батя, и так всё пройдёт)

18

ну натравите на него ваш же скриптец из соседней темы.... ag

19

odin пишет:

ну натравите на него ваш же скриптец из соседней темы.... ag

не для того я его писал.

Карусель разнесло по цепочке за час
Всех известий — конец
Да, весна началась!
(всё к лицу подлецу, как родному отцу, не рассказывай, батя, и так всё пройдёт)

20

drBatty пишет:

odin, нет.
это быдлокод. извините.

Поясните.

То что не убивает нас, делает нас сильнее! © Ницше.
When life puts you in tough situations, don’t say "why me". Just say "try me".
GNU/Linux Debian

21

voral пишет:

Поясните.

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

Карусель разнесло по цепочке за час
Всех известий — конец
Да, весна началась!
(всё к лицу подлецу, как родному отцу, не рассказывай, батя, и так всё пройдёт)

22

drBatty пишет:

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

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

То что не убивает нас, делает нас сильнее! © Ницше.
When life puts you in tough situations, don’t say "why me". Just say "try me".
GNU/Linux Debian

23

voral пишет:

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

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

Карусель разнесло по цепочке за час
Всех известий — конец
Да, весна началась!
(всё к лицу подлецу, как родному отцу, не рассказывай, батя, и так всё пройдёт)

24

drBatty пишет:

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

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

То что не убивает нас, делает нас сильнее! © Ницше.
When life puts you in tough situations, don’t say "why me". Just say "try me".
GNU/Linux Debian

25

voral пишет:

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

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

Карусель разнесло по цепочке за час
Всех известий — конец
Да, весна началась!
(всё к лицу подлецу, как родному отцу, не рассказывай, батя, и так всё пройдёт)

26 (27.12.2010 15:14:33 отредактировано XRevan86)

voral
drBatty (в IRC)

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

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

#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;
}

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

27 (27.12.2010 02:21:56 отредактировано voral)

Darth Revan пишет:
    delete File;
    File = 0;
    if (File)
        File->write(Reply->readAll());
    return 0;
}

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

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

То что не убивает нас, делает нас сильнее! © Ницше.
When life puts you in tough situations, don’t say "why me". Just say "try me".
GNU/Linux Debian

28

voral пишет:

Я правда не пробовал, но мне кажется - тут работать будет, но нестабильно.

voral пишет:

тут работать будет

Прошу рассказать - как сделать рабочим.

29 (27.12.2010 18:05:31 отредактировано Civil)

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

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

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

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

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

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

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

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

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

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

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

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

30

Darth Revan пишет:

Прошу рассказать - как сделать рабочим.

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

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

HEADERS += HttpDownload.h
SOURCES += HttpDownload.cpp \
           main.cpp
QT += network
То что не убивает нас, делает нас сильнее! © Ницше.
When life puts you in tough situations, don’t say "why me". Just say "try me".
GNU/Linux Debian