在我的程序中,我需要下载一个文件,我看到了这篇文章:
http://www.java2s.com/Code/Cpp/Qt/DownloadfromURL.htm
此代码确实有效,但它不适合我的程序,因此我对其进行了重新编码。我还没有完成所有这些,但我已经编码了基础知识。但是,当我测试它时,会弹出一个发送错误报告窗口。
到目前为止,这是我的代码:
QtDownload.h
#include <QObject>
#include <QString>
#include <QNetworkAccessManager>
#include <QNetworkReply>
class QtDownload : public QObject
{
Q_OBJECT
public:
explicit QtDownload();
~QtDownload();
void setTarget(const QString& t);
private:
QNetworkAccessManager manager;
QNetworkReply* reply;
QString target;
void connectSignalsAndSlots();
signals:
public slots:
void download();
void downloadFinished(QNetworkReply* data);
void downloadProgress(qint64 recieved, qint64 total);
};
QtDownload.cpp
#include "qtdownload.h"
#include <QUrl>
#include <QNetworkRequest>
#include <QFile>
QtDownload::QtDownload()
: QObject(0)
{
this->connectSignalsAndSlots();
}
QtDownload::~QtDownload()
{
if (reply != 0)
delete reply;
}
void QtDownload::connectSignalsAndSlots()
{
QObject::connect(&manager, SIGNAL(finished(QNetworkReply*)),this, SLOT(downloadFinished(QNetworkReply*)));
QObject::connect(reply, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(downloadProgress(qint64,qint64)));
}
void QtDownload::setTarget(const QString &t)
{
this->target = t;
}
void QtDownload::downloadFinished(QNetworkReply *data)
{
QFile localFile("downloadedfile");
if (!localFile.open(QIODevice::WriteOnly))
return;
localFile.write(data->readAll());
localFile.close();
delete data;
data = 0;
}
void QtDownload::download()
{
QUrl url = QUrl::fromEncoded(this->target.toLocal8Bit());
QNetworkRequest request(url);
this->reply = manager.get(request);
}
void QtDownload::downloadProgress(qint64 recieved, qint64 total)
{
}
的main.cpp
#include "qtdownload.h"
#include <QTimer>
int main()
{
QtDownload dl;
dl.setTarget("http://www.java2s.com/Code/Cpp/Qt/DownloadfromURL.htm");
QTimer::singleShot(0, &dl, SLOT(download()));
}
正如我所说,它还没有完全完成,但我希望这部分在我继续前工作。
我也是Qt的新手,所以任何提示都会受到赞赏。
答案 0 :(得分:5)
reply
初始化NULL
。reply
之后连接reply = manager.get(...)
,而不是在构造函数内部。{/ li>
{li> QNetworkReply
永远不会被QNetworkManager
删除为docs say:请勿删除与此信号相连的插槽中的回复对象。使用deleteLater()。
因此,您不应在QNetworkReply
广告位中的finished
上致电删除。
finished
广告位设置中data
到0
只会将参数值设置为0
,而不是您的班级成员reply
。这是一段不必要的代码。您应该将reply
成员设置为NULL
。此外,每次获得数据块时都应考虑写入文件,因为在当前情况下整个文件将缓冲在内存中。当指向URL的文件很大时,它可能会导致软件的大量内存使用。
答案 1 :(得分:1)
您需要QCoreApplication才能启动Qt4的事件循环。 这样的事情应该有效(未经测试):
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();
}
编辑::新版本
我发现了一些问题:
data
内删除QtDownload::downloadFinished
,不应该这样做,它由Qt处理,因此会被删除两次。reply
3次。以下是修改后的版本:
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();
}
答案 2 :(得分:1)
正如您所要求的,一些一般性意见:
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-&gt; readAll())无法保证一次写入所有数据。这就是为什么它有一个你应该检查的返回值,以确保所有内容都被写入。如果返回-1,则应该处理错误。
if (reply != 0)
delete reply;
省略if。删除空指针是安全的。