Qt 5 Download A File

First, for both Windows and Linux, add the following line to your application’s .pro file:

QT += network

For Windows applications:

myclass.h:


#include <QString>
#include <QLineEdit>

class myclass
{

Q_OBJECT

public:

void downloadFile(const QString &url, const QString &aPathInClient);

void myprocedure();

};

First, add the following lines to the top of your myclass.cpp file:

#include "myclass.h";
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QObject>
#include <QMessageBox>
#include <QStandardPaths>

You might have to run qmake after adding these lines to get the compiler to recognize these objects.

Then create a procedure in your class like the following:

myclass.cpp:

void myclass::downloadFile(const QString &url, const QString &aPathInClient)
{
    QNetworkAccessManager m_NetworkMngr;
    QNetworkReply *reply= m_NetworkMngr.get(QNetworkRequest(url));
    QEventLoop loop;
    QObject::connect(reply, SIGNAL(finished()),&loop, SLOT(quit()));
    loop.exec();
    QUrl aUrl(url);
    QFileInfo fileInfo=aUrl.path();

    QFile file(aPathInClient+"\\"+fileInfo.fileName());
    file.open(QIODevice::WriteOnly);
    file.write(reply->readAll());

    delete reply;

}

Then if you call the function in another class procedure, you can do it like the following. This is assuming you are using a folder in My Documents in the users Home directory.

myclass.cpp:

void myclass::myprocedure() {

    QString path;
    QString localpath;
    QMessageBox msgBox;
    QMessageBox msgBox2;

    path = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);

    path += "/My Documents/myfolder/";

    localPath = path;

    QMessageBox msgBox2;
    msgBox2.setText("You can download the update from the web.");
    msgBox2.setInformativeText("Do you want to download the file now?");
    msgBox2.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
    msgBox2.setDefaultButton(QMessageBox::Yes);
    int ret = msgBox2.exec();

    if (ret == QMessageBox::Yes) {

        downloadFile ("http://mywebsite.com/myfile.txt", localPath);

        msgBox.setText("Your file should be updated now");
        msgBox.exec();

    }

    else {

        // Do something else

    }

}

For Linux applications:

myclass.h:

#include <QString>
#include <QLineEdit>

class myclass
{

public:

void downloadFile(const QString &url, const QString &aPathInClient);

void myprocedure();

};

myclass.cpp:

#include "myclass.h";
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QObject>
#include <QMessageBox>
#include <QStandardPaths>

void myclass::downloadFile(const QString &url, const QString &aPathInClient)
{
    QNetworkAccessManager m_NetworkMngr;
    QNetworkReply *reply= m_NetworkMngr.get(QNetworkRequest(url));
    QEventLoop loop;
    QObject::connect(reply, SIGNAL(finished()),&loop, SLOT(quit()));
    loop.exec();
    QUrl aUrl(url);
    QFileInfo fileInfo=aUrl.path();

    QFile file(aPathInClient+"/"+fileInfo.fileName());
    file.open(QIODevice::WriteOnly);
    file.write(reply->readAll());

    delete reply;

}

Then when you call it:

void myclass::myprocedure() {

    QString path;
    QString localpath;
    QMessageBox msgBox;
    QMessageBox msgBox2;

    path = QStandardPaths::writableLocation(QStandardPaths::HomeLocation);

    path += "/myfolder";

    localPath = path;

    QMessageBox msgBox2;
    msgBox2.setText("You can download the update from the web.");
    msgBox2.setInformativeText("Do you want to download the file now?");
    msgBox2.setStandardButtons(QMessageBox::Yes | QMessageBox::No);
    msgBox2.setDefaultButton(QMessageBox::Yes);
    int ret = msgBox2.exec();

    if (ret == QMessageBox::Yes) {

        downloadFile ("http://mywebsite.com/myfile.txt", localPath);

        msgBox.setText("Your file should be updated now");
        msgBox.exec();

    }

    else {

        // Do something else

    }

}

Some developers don’t like using event loops to download files, like in the previous example. So here’s an alternative method that uses a synchronous download.

For Windows applications:

myclass.h:

#include <QString>
#include <QLineEdit>
#include <QNetworkAccessManager>
#include <QNetworkReply>

class myclass:public QOject
{

    Q_OBJECT

    public slots:

    void onRequestCompleted();

    public:

    QString df_url;
    QString df_path;
    QNetworkAccessManager *m_NetworkMngr;
    QNetworkReply *reply;

    public:

       void downloadFile(const QString &url, const QString &aPathInClient);

       void myprocedure();

};

First, add the following lines to the top of your myclass.cpp file:

#iclude “myclass.h”;
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QObject>
#include <QMessageBox>
#include <QStandardPaths>

You might have to run qmake after adding these lines to get the compiler to recognize these objects.

Then create procedures in your class like the following:

myclass.cpp:

The method myprocedure used in the first example would be the same.

void myclass::downloadFile(const QString &url, const QString &aPathInClient)
{

    QMessageBox msgBox;
    QString msgBoxText;

    df_url = url;
    df_path = aPathInClient;
    m_NetworkMngr = new QNetworkAccessManager(this);

    reply= m_NetworkMngr->get(QNetworkRequest(url));

    QObject::connect(reply, SIGNAL(finished()), this, SLOT(onRequestCompleted()));

}

void myclass::onRequestCompleted() {

    QString url2;
    QString aPathInClient2;

    url2 = df_url;
    aPathInClient2 = df_path;


    QUrl aUrl(url2);
    QFileInfo fileInfo=aUrl.path();

    QFile file(aPathInClient2+"/"+fileInfo.fileName());
    file.open(QIODevice::WriteOnly);
    file.write(reply->readAll());
    file.close();

}

Forgive the redundant use of variables for url and path, but this is the quickest way I did it, and haven’t re-worked the code yet to clean it up.

Advertisements