Files
Updater/Src/downloader.h
T
2026-04-29 23:16:10 +08:00

134 lines
4.7 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#ifndef DOWNLOADER_H
#define DOWNLOADER_H
#include <QObject>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QUrl>
#include <QFile>
#include <QDir>
extern QString CHECK_URL;
class Downloader : public QObject
{
Q_OBJECT
public:
/**
* @brief 构造联网下载器。
* @param parent Qt 父对象,负责随父对象析构自动释放网络管理器。
*
* 设计意图:Downloader 只负责单文件下载和本地落盘,不直接操作界面。
* 网络请求、QFile 都运行在创建它的线程中,外部跨线程调用时应使用信号槽队列连接,
* 避免在其它线程直接读写 QFile 或 QNetworkReply。
*/
explicit Downloader(QObject *parent = nullptr);
/**
* @brief 设置默认下载地址。
* @param url 输入的远程文件 URL;为空或非法时不会主动下载。
*/
void setUrl(const QString &);
/**
* @brief 开始下载文件。
* @param url 可选下载地址;为空时使用 setUrl() 已保存的地址。
*
* 输出通过 doProgress/doFinished/onError/doShowInfo 信号返回。
* 边界条件:同一 Downloader 同时只允许一个请求;目标文件名为空或 URL 非法会直接报错。
* 资源风险:下载过程写入 .part 临时文件,成功后替换为目标文件名;异常时关闭文件并清理网络对象。
*/
void startDownload(const QString &url = QString());
/**
* @brief 触发版本检测请求。
*
* 当前接口保留兼容旧调用;版本检测结果由 QNetworkAccessManager::finished 处理。
*/
void checkVersion();
/**
* @brief 获取当前落盘文件对象。
* @return 下载完成后的 QFile 引用;调用方只应读取文件名/路径,不应在下载中修改其打开状态。
*/
const QFile &getFile() const;
/**
* @brief 获取下载目录。
* @return 应用程序目录;用于外部定位下载包。
*/
const QDir &getDir() const;
/**
* @brief 获取目标文件名。
* @return 不包含目录的本地文件名。
*/
const QString &fileName() const;
/**
* @brief 设置目标文件名。
* @param newFileName 不包含路径的文件名,避免远程响应头异常覆盖任意目录。
*/
void setFileName(const QString &newFileName);
public slots:
signals:
/** @brief 下载进度,received/total 单位为字节;total 为 -1 时表示服务器未给出总长度。 */
void doProgress(qint64, qint64);
/** @brief 网络错误通知;错误发生后 Downloader 会关闭文件并释放 reply。 */
void onError(QNetworkReply::NetworkError);
/** @brief 下载完成通知;仅在网络无错误且临时文件成功改名后发出。 */
void doFinished();
/** @brief 文本状态通知,用于把边界条件、文件错误等信息显示到界面。 */
void doShowInfo(const QString&);
private:
/**
* @brief 关闭当前请求并释放 QNetworkReply。
* @param removePartial 为 true 时删除 .part 临时文件,常用于错误/取消场景。
*
* 设计意图:统一网络对象和文件句柄的释放路径,避免 finished/error 分支重复清理导致二次关闭。
*/
void cleanupCurrentReply(bool removePartial);
/**
* @brief 计算临时下载文件的完整路径。
* @return 当前目标文件名对应的 .part 路径;文件名为空时返回空字符串。
*/
QString partialFilePath() const;
/**
* @brief 计算最终下载文件的完整路径。
* @return 当前目标文件名对应的最终路径;文件名为空时返回空字符串。
*/
QString targetFilePath() const;
/** @brief 网络访问管理器,归 Downloader 父子对象树管理,必须在同一线程使用。 */
QNetworkAccessManager *m_pNetWorkAccessManager{nullptr};
/** @brief 当前下载响应对象,finished 后通过 deleteLater 释放,避免悬空回调。 */
QNetworkReply *m_pReply{nullptr};
/** @brief 正在下载标识,防止重复点击造成多个请求同时写同一个文件。 */
bool m_bIsDownloading = false;
/** @brief 当前下载 URLstartDownload 允许临时覆盖该地址。 */
QUrl m_pUrl{};
/** @brief 本地目标文件名,仅保存文件名不保存目录,避免路径注入。 */
QString m_fileName = "";
/** @brief 下载落盘文件句柄,下载中指向 .part 文件,完成后指向正式文件。 */
QFile file;
/** @brief 下载目录,默认应用程序目录;目录不存在时 startDownload 会创建。 */
QDir dir;
};
#endif // DOWNLOADER_H