update:运行多文件同时下载

This commit is contained in:
2025-06-13 09:04:25 +08:00
parent 50c916a8cc
commit 73a3733bc1
2 changed files with 69 additions and 23 deletions

View File

@@ -1,44 +1,62 @@
#include "downloadmanager.h" #include "downloadmanager.h"
#include <QFileInfo> #include <QFileInfo>
#include <QDir>
#include <QFile>
#include <QRegularExpression> #include <QRegularExpression>
#include <QDebug> #include <QDebug>
DownloadManager::DownloadManager(QObject *parent) : QObject(parent) {} DownloadManager::DownloadManager(QObject *parent) : QObject(parent)
{
cleanupTempFiles();
}
void DownloadManager::startDownload(const QString &packageName, const QString &url, const QString &outputPath) void DownloadManager::startDownload(const QString &packageName, const QString &url, const QString &outputPath)
{ {
if (m_processes.contains(packageName)) {
qWarning() << packageName << " is already downloading.";
return;
}
QString metalinkUrl = url + ".metalink"; QString metalinkUrl = url + ".metalink";
QStringList arguments; QFileInfo fileInfo(outputPath);
arguments << "--enable-rpc=false"
<< "--console-log-level=warn" QStringList arguments = {
<< "--summary-interval=1" "--enable-rpc=false",
<< "--dir=" + QFileInfo(outputPath).absolutePath() "--console-log-level=warn",
<< "--out=" + QFileInfo(outputPath).fileName() "--summary-interval=1",
<< metalinkUrl; "--allow-overwrite=true",
"--dir=" + fileInfo.absolutePath(),
"--out=" + fileInfo.fileName(),
metalinkUrl
};
QProcess *process = new QProcess(this); QProcess *process = new QProcess(this);
m_processes.insert(packageName, process); m_processes.insert(packageName, process);
// ✅ 改为按行读取(逐行处理) connect(process, &QProcess::readyReadStandardOutput, this, [this, packageName, process]() {
connect(process, &QProcess::readyReadStandardOutput, [this, process, packageName]() {
while (process->canReadLine()) { while (process->canReadLine()) {
QString line = process->readLine().trimmed(); QString line = QString::fromUtf8(process->readLine()).trimmed();
QRegularExpression regex(R"(\((\d+)%\))"); QRegularExpression regex(R"(\((\d+)%\))");
QRegularExpressionMatch match = regex.match(line); QRegularExpressionMatch match = regex.match(line);
if (match.hasMatch()) { if (match.hasMatch()) {
int progress = match.captured(1).toInt(); int progress = match.captured(1).toInt();
emit downloadProgress(packageName, progress); emit downloadProgress(packageName, progress);
qDebug() << "下载进度:" << progress << "%";
} }
} }
}); });
// 下载完成
connect(process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished), connect(process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
[this, packageName](int exitCode, QProcess::ExitStatus exitStatus) { this, [this, packageName, outputPath](int exitCode, QProcess::ExitStatus status) {
bool success = (exitCode == 0 && exitStatus == QProcess::NormalExit); bool success = (exitCode == 0 && status == QProcess::NormalExit);
if (!success) {
qWarning() << "Download failed for" << packageName << "exit code:" << exitCode;
}
removeAria2Files(outputPath); // 清理残留 .aria2
emit downloadFinished(packageName, success); emit downloadFinished(packageName, success);
m_processes.remove(packageName);
QProcess *proc = m_processes.take(packageName);
if (proc) proc->deleteLater();
}); });
process->start("aria2c", arguments); process->start("aria2c", arguments);
@@ -46,10 +64,35 @@ void DownloadManager::startDownload(const QString &packageName, const QString &u
void DownloadManager::cancelDownload(const QString &packageName) void DownloadManager::cancelDownload(const QString &packageName)
{ {
if (m_processes.contains(packageName)) { if (!m_processes.contains(packageName)) return;
QProcess *process = m_processes[packageName];
process->terminate(); QProcess *process = m_processes.take(packageName);
process->waitForFinished(); if (process) {
m_processes.remove(packageName); process->kill(); // 立即终止
process->waitForFinished(3000); // 最多等待3秒
process->deleteLater();
}
emit downloadFinished(packageName, false); // 显式通知取消
}
void DownloadManager::removeAria2Files(const QString &filePath)
{
QString ariaFile = filePath + ".aria2";
QFile::remove(ariaFile);
}
bool DownloadManager::isDownloading(const QString &packageName) const
{
return m_processes.contains(packageName);
}
void DownloadManager::cleanupTempFiles()
{
QDir tempDir(QDir::tempPath());
QStringList leftovers = tempDir.entryList(QStringList() << "*.aria2", QDir::Files);
for (const QString &f : leftovers) {
tempDir.remove(f);
} }
} }

View File

@@ -2,23 +2,26 @@
#define DOWNLOADMANAGER_H #define DOWNLOADMANAGER_H
#include <QObject> #include <QObject>
#include <QProcess>
#include <QMap> #include <QMap>
#include <QProcess>
class DownloadManager : public QObject class DownloadManager : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit DownloadManager(QObject *parent = nullptr); explicit DownloadManager(QObject *parent = nullptr);
void startDownload(const QString &packageName, const QString &url, const QString &outputPath); void startDownload(const QString &packageName, const QString &url, const QString &outputPath);
void cancelDownload(const QString &packageName); void cancelDownload(const QString &packageName);
bool isDownloading(const QString &packageName) const;
signals: signals:
void downloadProgress(const QString &packageName, int progress); void downloadProgress(const QString &packageName, int progress);
void downloadFinished(const QString &packageName, bool success); void downloadFinished(const QString &packageName, bool success);
private: private:
void cleanupTempFiles();
void removeAria2Files(const QString &filePath);
QMap<QString, QProcess*> m_processes; QMap<QString, QProcess*> m_processes;
}; };