qt https 下载文件

#ifndef FILEDOWNLOADER_H  
#define FILEDOWNLOADER_H  

#include <QObject>  
#include <QNetworkAccessManager>  
#include <QUrl>  
#include <QFile>  
#include <QCryptographicHash>  
#include <QNetworkReply>

class FileDownloader : public QObject {
    Q_OBJECT

public:
    explicit FileDownloader(const QUrl& url, const QString& outputDir, const QString& fileExtension, QObject* parent = nullptr);
    void download();
    //void stopDownload();  // 停止下载接口  

signals:
    void downloadFinished(bool success, const QString& filePath);
    void downloadProgress(qint64 bytesReceived, qint64 bytesTotal);
private slots:
    void startDownload();
    void onReadyRead();
    void onFinished();
    void onErrorOccurred(QNetworkReply::NetworkError code);
    //void downloadProgress(qint64 bytesReceived, qint64 bytesTotal);
private:
    void retryDownload();
    QString calculateMD5(const QString& filePath);
    void openFileLocation(const QString& filePath);

    QUrl url;
    QString outputDir;
    QString fileExtension;  // 指定的文件后缀  
    int retryCount;
    const int maxRetries;
    QNetworkAccessManager networkManager;
    QScopedPointer<QFile> file;
    QNetworkReply* reply;
    QString tempFilePath;
};

#endif // FILEDOWNLOADER_H

#include "FileDownloader.h"  
#include <QNetworkRequest>  
#include <QNetworkReply>  
#include <QTimer>  
#include <QDebug>  
#include <QFileInfo>  
#include <QDesktopServices>  
#include <QUrl>  
#include <QDir>  
#include <QProcess>
#include <QFile>  
#include <QDebug> 

FileDownloader::FileDownloader(const QUrl& url, const QString& outputDir, const QString& fileExtension, QObject* parent)
    : QObject(parent), url(url), outputDir(outputDir), fileExtension(fileExtension), retryCount(0), maxRetries(5), reply(nullptr) {
    connect(&networkManager, &QNetworkAccessManager::finished, this, &FileDownloader::onFinished);
    tempFilePath = "temp_download_file";  // 临时文件名  
}

void FileDownloader::download() {
    qDebug() << "Starting download:" << url;
    startDownload();
}

void FileDownloader::startDownload() {
    if (reply) {
        // 确保任何现有的回复在开始新下载之前得到处理  
        reply->abort();
        reply->deleteLater();
        reply = nullptr;
    }

    QNetworkRequest request(url);
    request.setRawHeader("User-Agent", "QtFileDownloader 1.0");

    reply = networkManager.get(request);
    connect(reply, &QNetworkReply::readyRead, this, &FileDownloader::onReadyRead);
    connect(reply, &QNetworkReply::finished, this, &FileDownloader::onFinished);
    connect(reply, &QNetworkReply::errorOccurred, this, &FileDownloader::onErrorOccurred);
    connect(reply, &QNetworkReply::downloadProgress, this, &FileDownloader::downloadProgress);
    file.reset(new QFile(tempFilePath));
    if (!file->open(QIODevice::WriteOnly)) {
        qWarning() << "Could not open file for writing:" << tempFilePath;
        retryDownload();
    }
}

void FileDownloader::onReadyRead() {
    if (file && reply) {
        file->write(reply->readAll());
    }
}
 

bool deleteFile(const QString& filePath) {
    QFile file(filePath);

    if (file.exists()) {
        if (file.remove()) {
            qDebug() << "File deleted successfully:" << filePath;
            return true;
        }
        else {
            qWarning() << "Failed to delete file:" << filePath;
            return false;
        }
    }
    else {
        qWarning() << "File does not exist:" << filePath;
        return false;
    }
}

void FileDownloader::onFinished() {
    if (reply) {
        if (reply->error() == QNetworkReply::NoError) {
            qDebug() << "Download finished successfully.";
            file->flush();
            file->close();

            QString md5Hash = calculateMD5(tempFilePath);
            QString newDirPath = QDir::current().filePath(outputDir);  // 使用指定输出目录  
            QString newFilePath = QDir(newDirPath).filePath(md5Hash + fileExtension);

            QDir dir(newDirPath);
            if (!dir.exists()) {
                dir.mkpath(newDirPath);  // 创建目录  
            }
            //DeleteFile()
            deleteFile(newFilePath);
            if (QFile::rename(tempFilePath, newFilePath)) {
                qDebug() << "File moved to:" << newFilePath;
                emit downloadFinished(true, newFilePath);
                openFileLocation(newFilePath);
            }
            else {
                qWarning() << "Failed to move file to destination directory.";
            }
        }
        else {
            retryDownload();
        }

        reply->deleteLater();
        reply = nullptr;
    }
}

void FileDownloader::onErrorOccurred(QNetworkReply::NetworkError code) {
    qWarning() << "Network error occurred:" << code;
    retryDownload();
}

void FileDownloader::retryDownload() {
    if (reply) {
        reply->abort();
        reply->deleteLater();
        reply = nullptr;
    }

    file.reset();

    if (retryCount < maxRetries) {
        retryCount++;
        qDebug() << "Retrying... Attempt" << retryCount;
        QTimer::singleShot(2000, this, &FileDownloader::startDownload); // 2秒后重试  
    }
    else {
        qWarning() << "Max retries reached. Download failed.";
        emit downloadFinished(false, QString());
    }
}

QString FileDownloader::calculateMD5(const QString& filePath) {
    QFile file(filePath);
    if (!file.open(QIODevice::ReadOnly)) {
        qWarning() << "Failed to open file for MD5 calculation:" << filePath;
        return QString();
    }

    QCryptographicHash hash(QCryptographicHash::Md5);
    if (hash.addData(&file)) {
        return hash.result().toHex();
    }
    return QString();
}

void FileDownloader::openFileLocation(const QString& filePath) {
    QFileInfo fileInfo(filePath);
#ifdef Q_OS_WIN  
    QString explorer = "explorer.exe";
    QStringList args;
    args << "/select," << QDir::toNativeSeparators(fileInfo.absoluteFilePath());
    QProcess::startDetached(explorer, args);
#elif defined(Q_OS_MAC)  
    QStringList args;
    args << "-e";
    args << QString("tell application \"Finder\" to reveal POSIX file \"%1\"").arg(fileInfo.absoluteFilePath());
    QProcess::execute("/usr/bin/osascript", args);
#elif defined(Q_OS_LINUX)  
    // For Linux, we try a variety of common file managers  
    QProcess::startDetached("xdg-open", QStringList() << fileInfo.absolutePath());
#else  
    // Fallback using the original method if not handled above  
    QDesktopServices::openUrl(QUrl::fromLocalFile(fileInfo.absolutePath()));
#endif  
}

//调用测试

    QUrl url("https://www.ffmpeg.org/releases/ffmpeg-5.1.3.tar.xz");  // Replace with your URL

    QString outputDir = "12345678";//指定下载到哪个文件夹
    FileDownloader downloader(url,outputDir,".dat");//指定下载文件后缀为.dat 文件名称以md5 命名
    QObject::connect(&downloader, &FileDownloader::downloadFinished, [&](bool success,const QString&fileName) {
        if (success) {
            qDebug() << "Download completed successfully. Saved as:" << fileName;
        } else {
            qDebug() << "Download failed.";
        }
        QCoreApplication::quit();
    });

    downloader.download();

//tls 初始化错误 参考

Qt TLS initialization failed 问题解决-CSDN博客

openssl 的几个dll拷贝到运行目录就可以了

  • 20
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值