头文件
#ifndef __LIB_DOWNLOAD_H__
#define __LIB_DOWNLOAD_H__
#include <memory>
#include <QObject>
#include <QUrl>
#include <QFile>
#include <QDir>
#include <QPointer>
#include <QApplication>
#include <QNetworkReply>
#include <QNetworkAccessManager>
#include <QStandardPaths>
class DownLoadFileHttps : public QObject
{
Q_OBJECT
public:
// 参数1=下载链接 参数2=保存的路径 参数3=父窗口地址
explicit DownLoadFileHttps(const QString& downloadUrl,
const QString& fileName,
QObject* parent = nullptr);
//析构,不解释
~DownLoadFileHttps();
bool startDownload(); // 开始下载文件
void cancelDownload(); // 取消下载文件
Q_SIGNALS:
// 下载进度信号
void sigProgress(qint64 bytesRead, qint64 totalBytes, qreal progress);
// 下载完成信号
void sigDownloadFinished();
private Q_SLOTS:
// QNetworkReply::finished对应的槽函数
void httpFinished();
// QIODevice::readyRead对应的槽函数
void httpReadyRead();
// QNetworkReply::downloadProgress对应的槽函数
void networkReplyProgress(qint64 bytesRead, qint64 totalBytes);
private:
void startRequest(const QUrl& requestedUrl);
std::unique_ptr<QFile> openFileForWrite(const QString& fileName);
private:
// 保存构造时传入的下载url
QString m_downloadUrl;
// 保存构造时传入的保存路径
QString m_savePath;
// 默认文件名称
QString m_fileName; // = "QConnect.exe";
QUrl url;
QNetworkAccessManager qnam;
QPointer<QNetworkReply> reply;
std::unique_ptr<QFile> m_fileptr;
bool httpRequestAborted;
// MainWindow *m_mainwindow;
};
#endif // DOWNLOADFILEHTTPS_H
cpp
#include "lib_download.h"
#include <hv/hlog.h>
DownLoadFileHttps::DownLoadFileHttps(
const QString& downloadUrl,
const QString& fileName,
QObject* parent) : QObject(parent)
{
m_downloadUrl = downloadUrl;
m_fileName = fileName;
m_savePath = "";
}
DownLoadFileHttps::~DownLoadFileHttps()
{
}
bool DownLoadFileHttps::startDownload()
{
const QUrl newUrl = QUrl::fromUserInput(m_downloadUrl);
if (!newUrl.isValid()) {
QString msg = QString("Download failed: %1.").arg(reply->errorString());
hloge("%s", msg.toStdString().c_str());
return false;
}
QString svrloadFile = QStandardPaths::writableLocation(QStandardPaths::DownloadLocation);
//QString fileName = newUrl.fileName();
//qDebug() << "文件名为:" << fileName;
qDebug() << "srvloadFile: " << svrloadFile;
//判断文件名称是否正确
//if (fileName.isEmpty()) {
// fileName = defaultFileName;
//}
//判断传有路径,没有则默认路径
if (m_savePath.isEmpty()) {
m_savePath = svrloadFile;
}
//判断路径是否存在,不存在创建
if (!QFileInfo(m_savePath).isDir()) {
QDir dir;
dir.mkpath(m_savePath);
}
m_fileName.prepend(m_savePath + '/');
if (QFile::exists(m_fileName)) {//判断是否存在此文件
QFile::remove(m_fileName);
}
m_fileptr = openFileForWrite(m_fileName);
if (!m_fileptr) {
return false;
}
startRequest(newUrl);
return true;
}
void DownLoadFileHttps::cancelDownload()
{
httpRequestAborted = true;
reply->abort();
}
void DownLoadFileHttps::httpFinished()
{
QFileInfo fi;
if (m_fileptr) {
fi.setFile(m_fileptr->fileName());
m_fileptr->close();
m_fileptr.reset();
}
if (httpRequestAborted) {
return;
}
if (reply->error()) {
QFile::remove(fi.absoluteFilePath());
QString msg = QString("Download failed: %1.").arg(reply->errorString());
hloge("%s", msg.toStdString().c_str());
return;
}
const QVariant redirectionTarget = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
if (!redirectionTarget.isNull()) {
const QUrl redirectedUrl = url.resolved(redirectionTarget.toUrl());
m_fileptr = openFileForWrite(fi.absoluteFilePath());
if (!m_fileptr) {
return;
}
startRequest(redirectedUrl);
return;
}
Q_EMIT sigDownloadFinished();
//Q_EMIT m_mainwindow->sigDownloadFinished();
}
void DownLoadFileHttps::httpReadyRead()
{
if (m_fileptr) {
m_fileptr->write(reply->readAll());
}
}
void DownLoadFileHttps::networkReplyProgress(qint64 bytesRead, qint64 totalBytes)
{
qreal progress = qreal(bytesRead) / qreal(totalBytes);
Q_EMIT sigProgress(bytesRead, totalBytes, progress);
// qDebug() << QString::number(progress * 100, 'f', 2) << "% "
// << bytesRead / (1024 * 1024) << "MB" << "/" << totalBytes / (1024 * 1024) << "MB";
// Q_EMIT sigProgress(bytesRead, totalBytes, progress);
}
void DownLoadFileHttps::startRequest(const QUrl& requestedUrl)
{
try {
url = requestedUrl;
httpRequestAborted = false;
QSslConfiguration config = QSslConfiguration::defaultConfiguration();
config.setProtocol(QSsl::AnyProtocol);
config.setPeerVerifyMode(QSslSocket::VerifyNone);
QNetworkRequest request = QNetworkRequest(url);
request.setSslConfiguration(config);
reply = qnam.get(request);
connect(reply, &QNetworkReply::finished, this, &DownLoadFileHttps::httpFinished);
connect(reply, &QIODevice::readyRead, this, &DownLoadFileHttps::httpReadyRead);
connect(reply, &QNetworkReply::downloadProgress, this, &DownLoadFileHttps::networkReplyProgress);
//qDebug() << QString(tr("Downloading %1...").arg(url.toString()));
}
catch (...) {
return ;
}
}
std::unique_ptr<QFile> DownLoadFileHttps::openFileForWrite(const QString& fileName)
{
std::unique_ptr<QFile> file(new QFile(fileName));
if (!file->open(QIODevice::WriteOnly)) {
QString msg = QString("Unable to save the file %1: %2.")
.arg(QDir::toNativeSeparators(fileName), file->errorString());
hloge("%s", msg.toStdString().c_str());
return nullptr;
}
return file;
}