Using QNetworkAccessManager to download a file
-
Hi all,
In the following example:
downloader.h
:#ifndef DOWNLOADER_H #define DOWNLOADER_H #include <QObject> #include <QNetworkAccessManager> #include <QNetworkRequest> #include <QNetworkReply> #include <QUrl> #include <QDateTime> #include <QFile> #include <QDebug> class Downloader : public QObject { Q_OBJECT public: explicit Downloader(QObject *parent = nullptr); void doDownload(); public slots: void replyFinished(QNetworkReply*); private: QNetworkAccessManager* manager; }; #endif // DOWNLOADER_H
downloader.cpp
:#include "downloader.h" Downloader::Downloader(QObject *parent) : QObject(parent){ } //********************************************** void Downloader::doDownload() { manager = new QNetworkAccessManager(this); connect(manager, &QNetworkAccessManager::finished, this, &Downloader::replyFinished); manager->get(QNetworkRequest(QUrl("http://qt-project.org"))); } //****************************************************** void Downloader::replyFinished(QNetworkReply* reply) { if(reply->error()) { qDebug() << "ERROR!"; qDebug() << reply->errorString(); } else { qDebug() << "1) " << reply->header(QNetworkRequest::ContentTypeHeader).toString(); qDebug() << "2) " << reply->header(QNetworkRequest::LastModifiedHeader).toDateTime().toString(); qDebug() << "3) " << reply->header(QNetworkRequest::ContentLengthHeader).toULongLong(); qDebug() << "4) " << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); qDebug() << "5) " << reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString(); QFile* file = new QFile("C:/Users/ME/Desktop/downloaded.txt"); if(file->open(QFile::Append)) { qDebug() <<"The text file is open"; file->write(reply->readAll()); file->flush(); file->close(); } delete file; } reply->deleteLater(); }
main.cpp
:#include <QCoreApplication> #include "downloader.h" int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); Downloader d; d.doDownload(); return a.exec(); }
Why nothing is written in the downloaded.txt file please? Is it because the server, here the qt website, doesn't send any data and
...ContentLengthHeader).toULongLong()
is zero? -
I think done! :)
First I downloaded Win64 OpenSSL v1.1.1f EXE | MSI (experimental) 63MB Installer from https://slproweb.com/products/Win32OpenSSL.html. Then installed the program and went and copied the path: C:\Program Files\OpenSSL-Win64\bin. After these on Projects > Run > Run Environment > clicked on
path
and then the button "Append path" and pasted the above path.
Now the program works for both "http" and "https" websites and the text file is also populated from the data received by QNetwork reply.It's 4:55 am here. It's time to sleep now. :)
-
Hi all,
In the following example:
downloader.h
:#ifndef DOWNLOADER_H #define DOWNLOADER_H #include <QObject> #include <QNetworkAccessManager> #include <QNetworkRequest> #include <QNetworkReply> #include <QUrl> #include <QDateTime> #include <QFile> #include <QDebug> class Downloader : public QObject { Q_OBJECT public: explicit Downloader(QObject *parent = nullptr); void doDownload(); public slots: void replyFinished(QNetworkReply*); private: QNetworkAccessManager* manager; }; #endif // DOWNLOADER_H
downloader.cpp
:#include "downloader.h" Downloader::Downloader(QObject *parent) : QObject(parent){ } //********************************************** void Downloader::doDownload() { manager = new QNetworkAccessManager(this); connect(manager, &QNetworkAccessManager::finished, this, &Downloader::replyFinished); manager->get(QNetworkRequest(QUrl("http://qt-project.org"))); } //****************************************************** void Downloader::replyFinished(QNetworkReply* reply) { if(reply->error()) { qDebug() << "ERROR!"; qDebug() << reply->errorString(); } else { qDebug() << "1) " << reply->header(QNetworkRequest::ContentTypeHeader).toString(); qDebug() << "2) " << reply->header(QNetworkRequest::LastModifiedHeader).toDateTime().toString(); qDebug() << "3) " << reply->header(QNetworkRequest::ContentLengthHeader).toULongLong(); qDebug() << "4) " << reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt(); qDebug() << "5) " << reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString(); QFile* file = new QFile("C:/Users/ME/Desktop/downloaded.txt"); if(file->open(QFile::Append)) { qDebug() <<"The text file is open"; file->write(reply->readAll()); file->flush(); file->close(); } delete file; } reply->deleteLater(); }
main.cpp
:#include <QCoreApplication> #include "downloader.h" int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); Downloader d; d.doDownload(); return a.exec(); }
Why nothing is written in the downloaded.txt file please? Is it because the server, here the qt website, doesn't send any data and
...ContentLengthHeader).toULongLong()
is zero?@tomy said in Using QNetworkAccessManager to download a file:
QFile* file = new QFile
There is no need to allocate file on the heap.
Was the file opened successfully?
Did you tryqDebug() << reply->readAll()
?
Also, if I open the URL in a browser I see that it is redirected to an HTTPS URL. Could be that you don't have working OpenSSL in your Qt set-up. -
@tomy said in Using QNetworkAccessManager to download a file:
QFile* file = new QFile
There is no need to allocate file on the heap.
Was the file opened successfully?
Did you tryqDebug() << reply->readAll()
?
Also, if I open the URL in a browser I see that it is redirected to an HTTPS URL. Could be that you don't have working OpenSSL in your Qt set-up.In,
QFile* file = new QFile("C:/Users/ME/Desktop/downloaded.txt"); if(file->open(QFile::Append)) { qDebug() <<"The text file is open"; file->write(reply->readAll()); file->flush(); file->close(); } delete file;
I have deleted
file
right at the point where it's not anymore needed. Is that heap allocation deprecated? Any general rule to obey, please?The
qDebug() <<"The text file is open";
works and outputs the message, so the file opens, I assume.you don't have working OpenSSL in your Qt set-up.
On my Qt set-up? Will you explain it please?
-
In,
QFile* file = new QFile("C:/Users/ME/Desktop/downloaded.txt"); if(file->open(QFile::Append)) { qDebug() <<"The text file is open"; file->write(reply->readAll()); file->flush(); file->close(); } delete file;
I have deleted
file
right at the point where it's not anymore needed. Is that heap allocation deprecated? Any general rule to obey, please?The
qDebug() <<"The text file is open";
works and outputs the message, so the file opens, I assume.you don't have working OpenSSL in your Qt set-up.
On my Qt set-up? Will you explain it please?
@tomy said in Using QNetworkAccessManager to download a file:
Is that heap allocation deprecated?
There is simply no need for heap allocation here. Also, stack allocation is a lot faster than heap.
Look, isn't this simpler?QFile file("C:/Users/ME/Desktop/downloaded.txt"); if(file.open(QFile::Append)) { qDebug() <<"The text file is open"; file.write(reply->readAll()); file.flush(); file.close(); }
And as additional bonus: you can't forget to delete it (as you could forget to put "delete file" there).
Take a look at https://doc.qt.io/qt-5/ssl.html
-
In,
QFile* file = new QFile("C:/Users/ME/Desktop/downloaded.txt"); if(file->open(QFile::Append)) { qDebug() <<"The text file is open"; file->write(reply->readAll()); file->flush(); file->close(); } delete file;
I have deleted
file
right at the point where it's not anymore needed. Is that heap allocation deprecated? Any general rule to obey, please?The
qDebug() <<"The text file is open";
works and outputs the message, so the file opens, I assume.you don't have working OpenSSL in your Qt set-up.
On my Qt set-up? Will you explain it please?
-
Take a look at https://doc.qt.io/qt-5/ssl.html
Thanks. I did but it's very confusing. I've not done this before. Let me explain please:
I downloaded openssl-1.1.1f and found the fileopensslv.h
in the include folder of it. Now should I add this file to "...\mingw73_64\bin" and include that header in thedownloader.h
?@Pablo-J-Rogina
Thank you. Why does the code have C style!?
Is this example not better? -
Take a look at https://doc.qt.io/qt-5/ssl.html
Thanks. I did but it's very confusing. I've not done this before. Let me explain please:
I downloaded openssl-1.1.1f and found the fileopensslv.h
in the include folder of it. Now should I add this file to "...\mingw73_64\bin" and include that header in thedownloader.h
?@Pablo-J-Rogina
Thank you. Why does the code have C style!?
Is this example not better?@tomy said in Using QNetworkAccessManager to download a file:
Is this example not better?
It's another example from same author. If you feel comfortable with that, it's Ok. It has a fancy GUI I guess
-
I myself created the GUI part by code in a project under the name GuiHttpDownload as follows:
GuiHttpDownload.h
#ifndef GUIHTTPDOWNLOAD_H #define GUIHTTPDOWNLOAD_H #include <QWidget> #include <QNetworkAccessManager> #include <QNetworkRequest> #include <QNetworkReply> #include <QUrl> #include <QDateTime> #include <QFile> #include <QDebug> class QPushButton; class QTextEdit; class GuiHttpDownload : public QWidget { Q_OBJECT public: GuiHttpDownload(QWidget *parent = nullptr); ~GuiHttpDownload(); public slots: void replyFinished(QNetworkReply*); private: QPushButton* download; QPushButton* quit; QTextEdit* textEdit; QNetworkAccessManager* manager; }; #endif // GUIHTTPDOWNLOAD_H
GuiHttpDownload.cpp
#include "guihttpdownload.h" #include <QPushButton> #include <QTextEdit> #include <QHBoxLayout> #include <QVBoxLayout> GuiHttpDownload::GuiHttpDownload(QWidget *parent) : QWidget(parent) { download = new QPushButton("&Download"); quit = new QPushButton("&Quit"); textEdit = new QTextEdit; manager = new QNetworkAccessManager(this); connect(manager, &QNetworkAccessManager::finished, this, &GuiHttpDownload::replyFinished); connect(download, &QPushButton::clicked, [this]() { this->manager->get(QNetworkRequest(QUrl("http://qt-project.org"))); }); connect(quit, &QPushButton::clicked, this, &GuiHttpDownload::close); QHBoxLayout* hLayout = new QHBoxLayout; hLayout->addWidget(download); hLayout->addWidget(quit); QVBoxLayout* vLayout = new QVBoxLayout; vLayout->addWidget(textEdit); vLayout->addLayout(hLayout); setLayout(vLayout); setWindowTitle("Download Test"); } //********************************************* GuiHttpDownload::~GuiHttpDownload() { delete download; delete quit; delete manager; } //*************************************************************** void GuiHttpDownload::replyFinished(QNetworkReply* reply) { if(reply->error()) { textEdit->insertPlainText("ERROR!"); textEdit->insertPlainText(reply->errorString()); } else { textEdit->insertPlainText("1) " + reply->header(QNetworkRequest::ContentTypeHeader).toString()); textEdit->insertPlainText("\n2) " + reply->header(QNetworkRequest::LastModifiedHeader).toDateTime().toString()); textEdit->insertPlainText("\n3) " + reply->header(QNetworkRequest::ContentLengthHeader).toULongLong()); textEdit->insertPlainText("\n4) " + reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt()); textEdit->insertPlainText("\n5) " + reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString()); QFile file("C:/Users/ME/Desktop/downloaded.txt"); if(file.open(QFile::Append)) { textEdit->insertPlainText("\n\nThe text file is open\n"); file.write(reply->readAll()); file.flush(); file.close(); } } reply->deleteLater(); }
main.cpp
#include "guihttpdownload.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); GuiHttpDownload w; w.show(); return a.exec(); }
It works rather fine. But still I've not found the correct way to have working OpenSSL in my Qt set-up!
@jsulm if possible, please help me on that.
Is the way I stated on my above post right for the job? I didn't find a solution to use it and solve the problem either. -
I myself created the GUI part by code in a project under the name GuiHttpDownload as follows:
GuiHttpDownload.h
#ifndef GUIHTTPDOWNLOAD_H #define GUIHTTPDOWNLOAD_H #include <QWidget> #include <QNetworkAccessManager> #include <QNetworkRequest> #include <QNetworkReply> #include <QUrl> #include <QDateTime> #include <QFile> #include <QDebug> class QPushButton; class QTextEdit; class GuiHttpDownload : public QWidget { Q_OBJECT public: GuiHttpDownload(QWidget *parent = nullptr); ~GuiHttpDownload(); public slots: void replyFinished(QNetworkReply*); private: QPushButton* download; QPushButton* quit; QTextEdit* textEdit; QNetworkAccessManager* manager; }; #endif // GUIHTTPDOWNLOAD_H
GuiHttpDownload.cpp
#include "guihttpdownload.h" #include <QPushButton> #include <QTextEdit> #include <QHBoxLayout> #include <QVBoxLayout> GuiHttpDownload::GuiHttpDownload(QWidget *parent) : QWidget(parent) { download = new QPushButton("&Download"); quit = new QPushButton("&Quit"); textEdit = new QTextEdit; manager = new QNetworkAccessManager(this); connect(manager, &QNetworkAccessManager::finished, this, &GuiHttpDownload::replyFinished); connect(download, &QPushButton::clicked, [this]() { this->manager->get(QNetworkRequest(QUrl("http://qt-project.org"))); }); connect(quit, &QPushButton::clicked, this, &GuiHttpDownload::close); QHBoxLayout* hLayout = new QHBoxLayout; hLayout->addWidget(download); hLayout->addWidget(quit); QVBoxLayout* vLayout = new QVBoxLayout; vLayout->addWidget(textEdit); vLayout->addLayout(hLayout); setLayout(vLayout); setWindowTitle("Download Test"); } //********************************************* GuiHttpDownload::~GuiHttpDownload() { delete download; delete quit; delete manager; } //*************************************************************** void GuiHttpDownload::replyFinished(QNetworkReply* reply) { if(reply->error()) { textEdit->insertPlainText("ERROR!"); textEdit->insertPlainText(reply->errorString()); } else { textEdit->insertPlainText("1) " + reply->header(QNetworkRequest::ContentTypeHeader).toString()); textEdit->insertPlainText("\n2) " + reply->header(QNetworkRequest::LastModifiedHeader).toDateTime().toString()); textEdit->insertPlainText("\n3) " + reply->header(QNetworkRequest::ContentLengthHeader).toULongLong()); textEdit->insertPlainText("\n4) " + reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt()); textEdit->insertPlainText("\n5) " + reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString()); QFile file("C:/Users/ME/Desktop/downloaded.txt"); if(file.open(QFile::Append)) { textEdit->insertPlainText("\n\nThe text file is open\n"); file.write(reply->readAll()); file.flush(); file.close(); } } reply->deleteLater(); }
main.cpp
#include "guihttpdownload.h" #include <QApplication> int main(int argc, char *argv[]) { QApplication a(argc, argv); GuiHttpDownload w; w.show(); return a.exec(); }
It works rather fine. But still I've not found the correct way to have working OpenSSL in my Qt set-up!
@jsulm if possible, please help me on that.
Is the way I stated on my above post right for the job? I didn't find a solution to use it and solve the problem either.@tomy said in Using QNetworkAccessManager to download a file:
But still I've not found the correct way to have working OpenSSL in my Qt set-up!
Could you please state:
- the OS
- how did you installed Qt framework?
- what compiler are you using?
-
@tomy said in Using QNetworkAccessManager to download a file:
But still I've not found the correct way to have working OpenSSL in my Qt set-up!
Could you please state:
- the OS
- how did you installed Qt framework?
- what compiler are you using?
-
@Pablo-J-Rogina
Could you please state:
- the OS
Windows 10 x64
- how did you installed Qt framework?
The online installer
- what compiler are you using?
MinGW x64
@tomy so then it's very likely the OpenSSL DLLs cannot be found by your app.
Please connect the QNetworkAccessManager::sslErrors() signal to a slot and check the error(s) there. -
I think done! :)
First I downloaded Win64 OpenSSL v1.1.1f EXE | MSI (experimental) 63MB Installer from https://slproweb.com/products/Win32OpenSSL.html. Then installed the program and went and copied the path: C:\Program Files\OpenSSL-Win64\bin. After these on Projects > Run > Run Environment > clicked on
path
and then the button "Append path" and pasted the above path.
Now the program works for both "http" and "https" websites and the text file is also populated from the data received by QNetwork reply.It's 4:55 am here. It's time to sleep now. :)