Qt网络编程之QNetworkRequest和QNetworkReply实例(四)

设想有如下场景:输入若干的url,然后依次的下载并存储到文件。本案例使用QNetworkRequest和QNetworkReply。源代码如下:

案例源码

头文件

#pragma once
//
//QNetworkReply/QNetworkRequest演示

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include 

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 

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等)的使用方式。

你可能感兴趣的:(Qt剖析)