In my program I need to download a file, and I came across this article:
http://www.java2s.com/Code/Cpp/Qt/DownloadfromURL.htm
This code does work but it d
As you asked for it, some general comments:
void QtDownload::downloadFinished(QNetworkReply *data)
{
QFile localFile("downloadedfile");
if (!localFile.open(QIODevice::WriteOnly))
return;
localFile.write(data->readAll());
localFile.close();
delete data;
data = 0;
}
localFile.write(data->readAll()) is not guaranteed to write all data at once. that's why it has a return value, which you should check, to make sure everything is written. If it returns -1, you should handle the error.
if (reply != 0)
delete reply;
Omit the if. Deleting a null pointer is safe.
reply with NULL in your constructor.reply after it was created (reply = manager.get(...)), not inside of your constructor.QNetworkReply is never deleted by QNetworkManager as docs say:Do not delete the reply object in the slot connected to this signal. Use deleteLater().
So you shouldn't call delete on QNetworkReply in finished slot.
finished slot setting data to 0 will only set parameter value to 0, not your class member reply. It's an unneeded line of code. You should set your reply member to NULL instead.Also you should consider writing to a file every time you get data chunk, as whole file will be buffered in memory in your current case. It may lead to huge memory usage of your software when file at pointed URL is big.
You need QCoreApplication to start the event loop for Qt4. Something like this should work (not tested) :
int main(int argc, char **argv) {
QCoreApplication app(argc, argv);
QtDownload dl;
dl.setTarget("http://www.java2s.com/Code/Cpp/Qt/DownloadfromURL.htm");
dl.download();
QObject::connect(app, SIGNAL(aboutToQuit()), app, SLOT(quit()));
return app.exec();
}
edit :: new version
I found some problems :
data inside QtDownload::downloadFinished, which shouldn't be done, it is handled by Qt, so it was getting deleted twice.reply 3 times.Here's the modified version :
qtdownload.h :
#include <QObject>
#include <QString>
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkReply>
class QtDownload : public QObject {
Q_OBJECT
public:
explicit QtDownload();
~QtDownload();
void setTarget(const QString& t);
private:
QNetworkAccessManager manager;
QString target;
signals:
void done();
public slots:
void download();
void downloadFinished(QNetworkReply* data);
void downloadProgress(qint64 recieved, qint64 total);
};
qtdownload.cpp :
#include "qtdownload.h"
#include <QCoreApplication>
#include <QUrl>
#include <QNetworkRequest>
#include <QFile>
#include <QDebug>
QtDownload::QtDownload() : QObject(0) {
QObject::connect(&manager, SIGNAL(finished(QNetworkReply*)),this, SLOT(downloadFinished(QNetworkReply*)));
}
QtDownload::~QtDownload() {
}
void QtDownload::setTarget(const QString &t) {
this->target = t;
}
void QtDownload::downloadFinished(QNetworkReply *data) {
QFile localFile("downloadedfile");
if (!localFile.open(QIODevice::WriteOnly))
return;
const QByteArray sdata = data->readAll();
localFile.write(sdata);
qDebug() << sdata;
localFile.close();
emit done();
}
void QtDownload::download() {
QUrl url = QUrl::fromEncoded(this->target.toLocal8Bit());
QNetworkRequest request(url);
QObject::connect(manager.get(request), SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(downloadProgress(qint64,qint64)));
}
void QtDownload::downloadProgress(qint64 recieved, qint64 total) {
qDebug() << recieved << total;
}
main.cpp :
#include <QtCore>
#include "qtdownload.h"
int main(int argc, char **argv) {
QCoreApplication app(argc, argv);
QtDownload dl;
dl.setTarget("http://localhost");
dl.download();
//quit when the download is done.
QObject::connect(&dl, SIGNAL(done()), &app, SLOT(quit()));
return app.exec();
}