Files
spark-store/spark-update-tool/src/downloadmanager.cpp
momen bc97519124 Add 'spark-update-tool/' from commit 'e5217b3829f4732887140066e6c3d33a120dc9da'
git-subtree-dir: spark-update-tool
git-subtree-mainline: 286f34f3f8
git-subtree-split: e5217b3829
2025-08-29 23:09:01 +08:00

118 lines
3.9 KiB
C++

#include "downloadmanager.h"
#include <QFileInfo>
#include <QDir>
#include <QFile>
#include <QRegularExpression>
#include <QDebug>
DownloadManager::DownloadManager(QObject *parent) : QObject(parent)
{
cleanupTempFiles();
}
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";
QFileInfo fileInfo(outputPath);
QStringList arguments = {
"--enable-rpc=false",
"--console-log-level=warn",
"--summary-interval=1",
"--allow-overwrite=true",
"--dir=" + fileInfo.absolutePath(),
"--out=" + fileInfo.fileName(),
metalinkUrl
};
QProcess *process = new QProcess(this);
m_processes.insert(packageName, process);
// 新增:准备日志文件
QString logPath = QString("/tmp/%1_download.log").arg(packageName);
QFile *logFile = new QFile(logPath, process);
if (logFile->open(QIODevice::Append | QIODevice::Text)) {
// 设置权限为777
QFile::setPermissions(logPath, QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner |
QFile::ReadGroup | QFile::WriteGroup | QFile::ExeGroup |
QFile::ReadOther | QFile::WriteOther | QFile::ExeOther);
connect(process, &QProcess::readyReadStandardOutput, this, [this, packageName, process, logFile]() {
while (process->canReadLine()) {
QString line = QString::fromUtf8(process->readLine()).trimmed();
// 写入日志
logFile->write(line.toUtf8() + '\n');
logFile->flush();
QRegularExpression regex(R"(\((\d+)%\))");
QRegularExpressionMatch match = regex.match(line);
if (match.hasMatch()) {
int progress = match.captured(1).toInt();
emit downloadProgress(packageName, progress);
}
}
});
connect(process, &QProcess::readyReadStandardError, this, [process, logFile]() {
QByteArray err = process->readAllStandardError();
logFile->write(err);
logFile->flush();
});
}
connect(process, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
this, [this, packageName, outputPath, logFile](int exitCode, QProcess::ExitStatus status) {
bool success = (exitCode == 0 && status == QProcess::NormalExit);
if (!success) {
qWarning() << "Download failed for" << packageName << "exit code:" << exitCode;
}
removeAria2Files(outputPath); // 清理残留 .aria2
emit downloadFinished(packageName, success);
if (logFile) logFile->close();
QProcess *proc = m_processes.take(packageName);
if (proc) proc->deleteLater();
});
process->start("aria2c", arguments);
}
void DownloadManager::cancelDownload(const QString &packageName)
{
if (!m_processes.contains(packageName)) return;
QProcess *process = m_processes.take(packageName);
if (process) {
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);
}
}