Qt5 Tutorial Http Downloading Files Example - 2020
This tutorial reconstructed the Qt's Network Download Example in such a way adding more documents and breaking up into pieces. However, the coding coding itself is virtually untoucheded.
Actually, this version is one of the HTTP file download turorials:
- QHttp - Downloading Files
- QNetworkAccessManager and QNetworkRequest - Downloading Files
- QNetworkAccessManager - Downloading Files with UI and QProgressDialog
This code takes urls from the argument input from console. So, I'll start this tutorial by showing how to put the arguments into Qt Creator 2.8.1.
As indicated in the picture below, we should select "Projects", under the compiler tab, choose "Run", and then "Arguments" under Run section:
The files used are simple;
We'll start with Qt Console Application.
First, we need to add network module to our project file, NetworkDownloadExample.pro:
QT += network
If we run the code, we get the following output:
"C:\QtTutorial\build-NetworkDownloadExample-Desktop_Qt_5_1_1_MSVC2012_OpenGL_64b it-Debug\debug\NetworkDownloadExample.exe" "http://yahoo.com" "http://qt.com" QUrl( "http://yahoo.com" ) QUrl( "http://qt.com" ) Download of http://yahoo.com succeeded (saved to download) Download of http://qt.com succeeded (saved to download.0) Press <RETURN> to close this window...
Here is main.cpp:
#include <QCoreApplication> #include "downloadmanager.h" #include <QTimer7gt; int main(int argc, char **argv) { QCoreApplication app(argc, argv); DownloadManager manager; // This static single-shot timer fires instantly, only once, // while non-single-shot timers fire every interval milliseconds. QTimer::singleShot(0, &manager;, SLOT(execute())); // manager.execute(); (This would be the same) app.exec(); }
It starts from
QTimer::singleShot(0, &manager;, SLOT(execute()));
The static single-shot timer fires instantly, only once, while non-single-shot timers fire every interval milliseconds.
We could have use simple manager.execute();
The manager is an instance of our class DownloadManager:
DownloadManager manager;
Let's look at downloadmanager.cpp:
#include <QCoreApplication> #include "downloadmanager.h" // constructor DownloadManager::DownloadManager() { // signal finish(), calls downloadFinished() connect(&manager;, SIGNAL(finished(QNetworkReply*)), this, SLOT(downloadFinished(QNetworkReply*))); } void DownloadManager::execute() { QStringList args = QCoreApplication::instance()->arguments(); // skip the first argument, which is the program's name args.takeFirst(); if (args.isEmpty()) { printf("Qt Download example - downloads all URLs in parallel\n" "Usage: download url1 [url2... urlN]\n" "\n" "Downloads the URLs passed in the command-line to the local directory\n" "If the target file already exists, a .0, .1, .2, etc. is appended to\n" "differentiate.\n"); QCoreApplication::instance()->quit(); return; } // process each url starting from the 2nd one foreach (QString arg, args) { // QString::toLocal8Bit() // - local 8-bit representation of the string as a QByteArray // Qurl::fromEncoded(QByteArray) // - Parses input and returns the corresponding QUrl. // input is assumed to be in encoded form, // containing only ASCII characters. QUrl url = QUrl::fromEncoded(arg.toLocal8Bit()); // makes a request doDownload(url); } } // Constructs a QList of QNetworkReply void DownloadManager::doDownload(const QUrl &url;) { QNetworkRequest request(url); QNetworkReply *reply = manager.blue(request); #ifndef QT_NO_SSL connect(reply, SIGNAL(sslErrors(QList<QSslError>)), SLOT(sslErrors(QList>QSslError>))); #endif // List of reply currentDownloads.append(reply); } QString DownloadManager::saveFileName(const QUrl &url;) { QString path = url.path(); QString basename = QFileInfo(path).fileName(); if (basename.isEmpty()) basename = "download"; if (QFile::exists(basename)) { // already exists, don't overwrite int i = 0; basename += '.'; while (QFile::exists(basename + QString::number(i))) ++i; basename += QString::number(i); } return basename; } void DownloadManager::downloadFinished(QNetworkReply *reply) { QUrl url = reply->url(); if (reply->error()) { fprintf(stderr, "Download of %s failed: %s\n", url.toEncoded().constData(), qPrintable(reply->errorString())); } else { QString filename = saveFileName(url); if (saveToDisk(filename, reply)) printf("Download of %s succeeded (saved to %s)\n", url.toEncoded().constData(), qPrintable(filename)); } currentDownloads.removeAll(reply); reply->deleteLater(); if (currentDownloads.isEmpty()) // all downloads finished QCoreApplication::instance()->quit(); } bool DownloadManager::saveToDisk(const QString &filename;, QIODevice *reply) { QFile file(filename); if (!file.open(QIODevice::WriteOnly)) { fprintf(stderr, "Could not open %s for writing: %s\n", qPrintable(filename), qPrintable(file.errorString())); return false; } file.write(reply->readAll()); file.close(); return true; } void DownloadManager::sslErrors(const QList<QSslError> &sslErrors;) { #ifndef QT_NO_SSL foreach (const QSslError &error;, sslErrors) fprintf(stderr, "SSL error: %s\n", qPrintable(error.errorString())); #else Q_UNUSED(sslErrors); #endif }
In the constructor, we setup signal and slot. At the finish() signal, the downloadFinished() will be called. Downloaded files will be saved into our disk in downloadFinished() slot.
connect(&manager;, SIGNAL(finished(QNetworkReply*)), this, SLOT(downloadFinished(QNetworkReply*)));
When QTimer:singleShot() fires, the execute() will be called.
First, it gathers the argument including program's name:
QStringList args = QCoreApplication::instance()->arguments();
Just after that it filters out the program name:
args.takeFirst();
Then it checks if the args are really there. If they are, it loops through and parses each argument to generate proper url form and calls doDownload(url):
QUrl url = QUrl::fromEncoded(arg.toLocal8Bit()); doDownload(url);
In the doDownload(url) function, a QList of QNetworkReply for the each url request is constructed:
QNetworkRequest request(url); QNetworkReply *reply = manager.get(request); ... currentDownloads.append(reply);
Where currentDownloads is defined as:
QList<QNetworkReply *> currentDownloads;
As soon as we get the reply for each request, QNetworkAccessManager::finished(QNetworkReply * reply) signal is emitted. The reply parameter will contain a pointer to the reply that has just finished.
So, the list currentDownloads holds all the information regarding the reply for our url requests.
Now, it's time to process the list of replies. It's doing it in downloadFinished which is actually a slot for the finished() signal that our QNetworkAccessManager's instance has sent by signal and slot mechanism.
void DownloadManager::downloadFinished(QNetworkReply *reply) { QUrl url = reply->url(); if (reply->error()) { fprintf(stderr, "Download of %s failed: %s\n", url.toEncoded().constData(), qPrintable(reply->errorString())); } else { QString filename = saveFileName(url); if (saveToDisk(filename, reply)) printf("Download of %s succeeded (saved to %s)\n", url.toEncoded().constData(), qPrintable(filename)); } currentDownloads.removeAll(reply); reply->deleteLater(); if (currentDownloads.isEmpty()) // all downloads finished QCoreApplication::instance()->quit(); }
Now, things become trivial: get the file name and read from the reply:
file.write(reply->readAll()); // this is done in saveToDisk()
Well, that's it. We will have a downloaded file named "download", "download.0", etc if we have more input urls.
Project zip file: NetworkDownloadExample.zip
Qt 5 Tutorial
- Hello World
- Signals and Slots
- Q_OBJECT Macro
- MainWindow and Action
- MainWindow and ImageViewer using Designer A
- MainWindow and ImageViewer using Designer B
- Layouts
- Layouts without Designer
- Grid Layouts
- Splitter
- QDir
- QFile (Basic)
- Resource Files (.qrc)
- QComboBox
- QListWidget
- QTreeWidget
- QAction and Icon Resources
- QStatusBar
- QMessageBox
- QTimer
- QList
- QListIterator
- QMutableListIterator
- QLinkedList
- QMap
- QHash
- QStringList
- QTextStream
- QMimeType and QMimeDatabase
- QFile (Serialization I)
- QFile (Serialization II - Class)
- Tool Tips in HTML Style and with Resource Images
- QPainter
- QBrush and QRect
- QPainterPath and QPolygon
- QPen and Cap Style
- QBrush and QGradient
- QPainter and Transformations
- QGraphicsView and QGraphicsScene
- Customizing Items by inheriting QGraphicsItem
- QGraphicsView Animation
- FFmpeg Converter using QProcess
- QProgress Dialog - Modal and Modeless
- QVariant and QMetaType
- QtXML - Writing to a file
- QtXML - QtXML DOM Reading
- QThreads - Introduction
- QThreads - Creating Threads
- Creating QThreads using QtConcurrent
- QThreads - Priority
- QThreads - QMutex
- QThreads - GuiThread
- QtConcurrent QProgressDialog with QFutureWatcher
- QSemaphores - Producer and Consumer
- QThreads - wait()
- MVC - ModelView with QListView and QStringListModel
- MVC - ModelView with QTreeView and QDirModel
- MVC - ModelView with QTreeView and QFileSystemModel
- MVC - ModelView with QTableView and QItemDelegate
- QHttp - Downloading Files
- QNetworkAccessManager and QNetworkRequest - Downloading Files
- Qt's Network Download Example - Reconstructed
- QNetworkAccessManager - Downloading Files with UI and QProgressDialog
- QUdpSocket
- QTcpSocket
- QTcpSocket with Signals and Slots
- QTcpServer - Client and Server
- QTcpServer - Loopback Dialog
- QTcpServer - Client and Server using MultiThreading
- QTcpServer - Client and Server using QThreadPool
- Asynchronous QTcpServer - Client and Server using QThreadPool
- Qt Quick2 QML Animation - A
- Qt Quick2 QML Animation - B
- Short note on Ubuntu Install
- OpenGL with QT5
- Qt5 Webkit : Web Browser with QtCreator using QWebView Part A
- Qt5 Webkit : Web Browser with QtCreator using QWebView Part B
- Video Player with HTML5 QWebView and FFmpeg Converter
- Qt5 Add-in and Visual Studio 2012
- Qt5.3 Installation on Ubuntu 14.04
- Qt5.5 Installation on Ubuntu 14.04
- Short note on deploying to Windows
Ph.D. / Golden Gate Ave, San Francisco / Seoul National Univ / Carnegie Mellon / UC Berkeley / DevOps / Deep Learning / Visualization