mirror of
https://gitee.com/spark-store-project/spark-store
synced 2025-12-20 03:01:36 +08:00
update:运行多文件同时下载
This commit is contained in:
@@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user