Qt網路程式設計之QNetworkRequest和QNetworkReply例項(四)
阿新 • • 發佈:2018-12-13
設想有如下場景:輸入若干的url,然後依次的下載並存儲到檔案。本案例使用QNetworkRequest和QNetworkReply。原始碼如下:
案例原始碼
標頭檔案
#pragma once
//////////////////////////////////////////////////////////////////////////
//QNetworkReply/QNetworkRequest演示
#include <QCoreApplication>
#include <QFile>
#include <QFileInfo>
#include <QList>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QSslError>
#include <QStringList>
#include <QTimer>
#include <QUrl>
#include <stdio.h>
QT_BEGIN_NAMESPACE
class QSslError;
QT_END_NAMESPACE
QT_USE_NAMESPACE
class DownloadManager : public QObject
{
Q_OBJECT
QNetworkAccessManager manager;
QList<QNetworkReply *> currentDownloads;
public:
DownloadManager();
void doDownload(const QUrl &url);
QString saveFileName(const QUrl &url);
bool saveToDisk(const QString &filename, QIODevice *data);
public slots:
void execute();
void downloadFinished(QNetworkReply *reply) ;
void sslErrors(const QList<QSslError> &errors);
};
void testDownloadManager();
原始檔
#include "DownloaderDemo.h"
#include <QDebug>
DownloadManager::DownloadManager()
{
//建立請求完成訊號槽
connect(&manager, SIGNAL(finished(QNetworkReply*)), SLOT(downloadFinished(QNetworkReply*)));
}
void DownloadManager::doDownload(const QUrl &url)
{
//構造網路請求
QNetworkRequest request(url);
QNetworkReply *reply = manager.get(request);
//開啟事件迴圈,請求結束在退出
QEventLoop oLoop;
connect(reply, SIGNAL(finished()), &oLoop, SLOT(quit()));
oLoop.exec();
#ifndef QT_NO_SSL
connect(reply, SIGNAL(sslErrors(QList<QSslError>)), SLOT(sslErrors(QList<QSslError>)));
#endif
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))
{
//已存在的檔案不覆蓋
int i = 0;
basename += '.';
while (QFile::exists(basename + QString::number(i)))
++i;
basename += QString::number(i);
}
return basename;
}
bool DownloadManager::saveToDisk(const QString &filename, QIODevice *data)
{
QFile file(filename);
if (!file.open(QIODevice::WriteOnly))
{
qDebug() << "Could not open " << filename << " for writing: " << file.errorString();
return false;
}
file.write(data->readAll());
file.close();
return true;
}
void DownloadManager::execute()
{
//新增下載的若干url
QStringList args;
args.push_back("https://blog.csdn.net/sun222555888/article/details/82917333");
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;
}
//依次遍歷下載url
foreach(QString arg, args)
{
QUrl url = QUrl::fromEncoded(arg.toLocal8Bit());
doDownload(url);
}
}
void DownloadManager::sslErrors(const QList<QSslError> &sslErrors)
{
#ifndef QT_NO_SSL
foreach(const QSslError &error, sslErrors)
qDebug() << "SSL error: " << error.errorString();
#else
Q_UNUSED(sslErrors);
#endif
}
void DownloadManager::downloadFinished(QNetworkReply *reply)
{
QUrl url = reply->url();
if (reply->error())
{
qDebug() << "Download of " << url.toEncoded().constData() << " failed: " << reply->errorString();
}
else
{
QString filename = saveFileName(url);
if (saveToDisk(filename, reply))
qDebug() << "Download of " << url.toEncoded().constData() << " succeeded saved to: " << filename;
}
currentDownloads.removeAll(reply);
reply->deleteLater();
if (currentDownloads.isEmpty())
//下載完成後退出程式
QCoreApplication::instance()->quit();
}
void testDownloadManager()
{
DownloadManager* pManager = new DownloadManager;
pManager->execute();
}
測試結果
Download of https://blog.csdn.net/sun222555888/article/details/82917333 succeeded saved to: "82917333.0"
經過測試驗證會將指定的url下載成檔案。本案例例項講解了QNetworkAccessManager/QNetworkRequest/QNetworkReply三者協作處理網路請求(http/https等)的使用方式。