Implementing filedownloader to QML



  • Hi,

    for my software, i need to download a file to my local HDD. I found this example:
    "Downloading file from URL":http://qt-project.org/forums/viewthread/16749
    and tried to use it. The result looks like this:

    main.cpp
    @
    //main.cpp
    #include <QtGui/QGuiApplication>
    #include "qtquick2applicationviewer.h"
    #include "filedownloader.h"
    #include <QQmlEngine>
    #include <QtQml>
    #include <QtDebug>
    #include <QObject>

    FileDownloader* n;
    QNetworkAccessManager* nam;
    QObject* parent;

    int main(int argc, char *argv[])
    {
    QGuiApplication app(argc, argv);
    QtQuick2ApplicationViewer viewer;
    QUrl imageURL("http://i.imgur.com/Uw7Fk.jpg");
    viewer.setMainQmlFile(QStringLiteral("qml/DownloadTest4/main.qml"));
    viewer.showExpanded();
    n = new FileDownloader(imageURL, parent);
    //app.connect(n, SIGNAL(downloaded()),SLOT);
    return app.exec();
    }@

    filedownloader.cpp
    @
    //filedownloader.cpp
    #include "filedownloader.h"
    #include <QDebug>
    #include <QFile>

    FileDownloader::FileDownloader(QUrl imageUrl, QObject parent) :
    QObject(parent)
    {
    connect(&m_WebCtrl, SIGNAL(finished(QNetworkReply
    )),
    SLOT(fileDownloaded(QNetworkReply*)));

    QNetworkRequest request(imageUrl);
    m_WebCtrl.get(request);
    qDebug()<<"Request sent!";
    

    }

    FileDownloader::~FileDownloader()
    {

    }

    void FileDownloader::fileDownloaded(QNetworkReply* pReply)
    {
    qDebug()<<"Download successful!";
    m_DownloadedData = pReply->readAll();
    QFile file("D:\Test.jpg");
    file.open(QIODevice::WriteOnly);
    file.write(pReply->readAll());
    //emit a signal
    pReply->deleteLater();
    emit downloaded();

    }

    QByteArray FileDownloader::downloadedData() const
    {
    return m_DownloadedData;
    }@

    filedownloader.h
    @
    //filedownloader.h
    #ifndef FILEDOWNLOADER_H
    #define FILEDOWNLOADER_H

    #include <QObject>
    #include <QByteArray>
    #include <QNetworkAccessManager>
    #include <QNetworkRequest>
    #include <QNetworkReply>

    class FileDownloader : public QObject
    {
    Q_OBJECT
    public:

    explicit FileDownloader(QUrl imageUrl, QObject *parent = 0);
    
    virtual ~FileDownloader();
    
    QByteArray downloadedData() const;
    

    signals:
    void downloaded();

    private slots:

    void fileDownloaded(QNetworkReply* pReply);
    

    private:

    QNetworkAccessManager m_WebCtrl;
    
    QByteArray m_DownloadedData;
    

    };

    #endif // FILEDOWNLOADER_H@

    Now i have the problem that i get my two console logs "Request sent!" and "Download successful!" but i can't find the file that should have been created.
    Am i doing anything wrong with QFile?

    My second problem is the including of "filedownloader.h" into a QML-file.

    I know that I have to register the C++ as a type, like this:
    @qmlRegisterType<filedownloader>("my.library", 1, 0, "FileDownloader");@
    but it's not working.

    I hope somebody can help me :)



  • Hi,

    in your example code you do:

    @void FileDownloader::fileDownloaded(QNetworkReply* pReply)
    {
    qDebug()<<"Download successful!";
    m_DownloadedData = pReply->readAll();
    QFile file("D:\Test.jpg");
    file.open(QIODevice::WriteOnly);
    file.write(pReply->readAll());
    //emit a signal
    pReply->deleteLater();
    emit downloaded();
    }
    @

    the line "m_DownloadedData = pReply->readAll();" creates this issue,

    after this line, the buffer of your network reply is empty, and the data is inside "m_DownloadedData"

    a few lines lower, you try to save the image by doing: "file.write(pReply->readAll());"

    but the buffer is already empty...

    so you shoud do: "file.write( m_DownloadedData );"

    i should do,

    @
    void FileDownloader::fileDownloaded(QNetworkReply* pReply)
    {
    qDebug()<<"Download successful!";
    QFile file("D:\Test.jpg");

    if( !file.open(QIODevice::WriteOnly) )
        return;  // file could not be created
    
    file.write(pReply->readAll());
    //emit a signal
    pReply->deleteLater();
    emit downloaded();
    

    }
    @

    and remove the variable "m_DownloadedData"

    for your second issue,

    you also have to include the macro QML_DECLARE_TYPE(CLASSNAME)
    in your header file, before you can use the qmlRegisterType method.

    so:

    @
    //filedownloader.h
    #ifndef FILEDOWNLOADER_H
    #define FILEDOWNLOADER_H

    #include <QtQml> // add for QML_DECLARE_TYPE macro !!!!!

    #include <QObject>
    #include <QByteArray>
    #include <QNetworkAccessManager>
    #include <QNetworkRequest>
    #include <QNetworkReply>

    class FileDownloader : public QObject
    {
    Q_OBJECT
    public:

    explicit FileDownloader(QUrl imageUrl, QObject *parent = 0);
    
    virtual ~FileDownloader();
    
    QByteArray downloadedData() const;
    

    signals:
    void downloaded();

    private slots:

    void fileDownloaded(QNetworkReply* pReply);
    

    private:

    QNetworkAccessManager m_WebCtrl;
    
    QByteArray m_DownloadedData;
    

    };

    QML_DECLARE_TYPE( FileDownloader ) // marco !!

    #endif // FILEDOWNLOADER_H
    @


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.