1. 程式人生 > >Qt網路程式設計之QNetworkRequest和QNetworkReply例項(四)

Qt網路程式設計之QNetworkRequest和QNetworkReply例項(四)

設想有如下場景:輸入若干的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等)的使用方式。