Upload file to Qt from URL

In my program, I need to upload a file, and I came across this article:

http://www.java2s.com/Code/Cpp/Qt/DownloadfromURL.htm

This code works, but it does not fit into my program, so I transcoded it. I have not finished everything, but I have encoded the basics. However, when I test it, it appears with an error message sending message.

So far this is my code:

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())); } 

As I said, it is not completely finished, but I want this part to work before I move on.

I am also new to Qt, so any advice would be appreciated.

+7
c ++ qt qt4
source share
3 answers
  • You are using an uninitialized pointer, so it points to nowhere. Initialize reply with NULL in your constructor.
  • You should connect reply after creating it ( reply = manager.get(...) ), and not inside your constructor.
  • QNetworkReply never deleted by QNetworkManager as docs say :

Do not delete the response object in the slot connected to this signal. Use deleteLater ().

Therefore, you should not call delete on QNetworkReply in the finished slot.

  • In the configuration of the finished data - 0 slot, only the value of parameter 0 will be set, and not your member of the reply class. This is an unnecessary line of code. You should set the member to NULL instead of reply .

You should also consider writing to a file every time you get a piece of data, since the entire file will be buffered in memory in your current case. This can lead to huge memory usage of your software when the file with the specified URL is large.

+5
source share

You need QCoreApplication to start the event loop for Qt4. Something like this should work (not verified):

 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:

  • You do not need a custom answer, nor do you ever set it to 0 in your constructor, so if it has never been used, it will delete a random piece of memory in your ~ QtDownload ();
  • you deleted data inside QtDownload::downloadFinished , which should not be done, it is processed by Qt, so it is deleted twice.
  • because of # 2 you delete 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(); } 
+1
source share

As you asked for this, some general notes:

 void QtDownload::downloadFinished(QNetworkReply *data) { QFile localFile("downloadedfile"); if (!localFile.open(QIODevice::WriteOnly)) return; localFile.write(data->readAll()); localFile.close(); delete data; data = 0; } 
  • You read all the data in one piece. Bad for large files. Better read it gradually.
  • Removing argument data from a slot is dangerous. You do not know if the network manager (or deletes) the "data" objects immediately after it emits a complete signal. You probably don't even need to delete the answer, if it belongs to the manager, check something in the documentation.
  • If files are not opened, data is not deleted. So, whatever is right, its inconsistency. Either you have a leak, or you have the risk of double deletion.
  • localFile.write (data-> readAll ()) does not guarantee writing all data at once. therefore, it has a return value that you must check to make sure everything is written. If it returns -1, you should handle the error.

     if (reply != 0) delete reply; 

Omit if. Removing a null pointer is safe.

+1
source share

All Articles