Inno Setup长文件列表下载后如何即时移动已完成的下载文件
Inno Setup 大文件下载后即时移动落地方案
问题根因
- 你之前用
OnDownloadProgress判断Progress = ProgressMax时执行移动操作失败的核心原因:该进度回调触发时仅代表网络流接收完成,Inno Download Plugin(IDP,即CodeDownloadFiles.iss示例对应的插件)尚未将缓存中最后一段数据写入{tmp}路径下的文件,文件句柄也未释放;同时此时下载队列已经切换到下一个待处理文件,回调传入的FileName参数可能已经对应下一个文件,必然出现复制失败、文件不全的问题。 - 用
[Files]段统一复制临时文件的方案会让大文件同时存在于临时目录和目标目录,临时占用双倍磁盘空间,不符合你的需求。
具体实现方案
优先选择下载完成后移动文件的方案,不建议修改插件默认临时下载目录,原因在后续方案对比部分说明。
IDP本身提供了专门的单文件下载完成回调OnFileDownloaded,触发时机为文件完全写入临时目录、句柄正常释放之后,完全匹配你「单文件下完就处理,不等待全部下载完成」的需求,实现代码如下:
- 首先在下载页初始化时绑定回调事件
procedure InitializeWizard; begin // 原有下载页初始化逻辑 DownloadPage := CreateDownloadPage(SetupMessage(msgWizardPreparing), SetupMessage(msgPreparingDesc), @OnDownloadProgress); // 新增:绑定单文件下载完成回调 DownloadPage.OnFileDownloaded := @OnSingleFileDownloaded; end;
- 实现单文件下载完成后的移动逻辑,优先用移动操作避免双倍空间占用
procedure OnSingleFileDownloaded(const Url, FileName: String); var TempFilePath, CacheFilePath: String; begin TempFilePath := ExpandConstant('{tmp}\' + FileName); CacheFilePath := ExpandConstant('{src}\storage\' + FileName); // 提前创建缓存目录,避免移动失败 ForceDirectories(ExtractFileDir(CacheFilePath)); // 同分区下FileMove是修改文件系统表,秒完成无额外IO、不占额外空间 if not FileMove(TempFilePath, CacheFilePath, False) then begin // 跨分区场景下移动失败,兜底用复制+删除原文件 FileCopy(TempFilePath, CacheFilePath, False); DeleteFile(TempFilePath); end; end;
- 修正你原有
CheckFileToDownload函数的返回值bug:原代码未给函数返回值Result赋值,会导致返回值随机,判断逻辑失效
function CheckFileToDownload(const Url, FileName, ComponentName: String): Boolean; begin Result := False; if WizardIsComponentSelected(ComponentName) then begin if not FileExists(ExpandConstant('{src}\storage\'+FileName)) then begin Inc(DownloadCount); Result := True; end; end; end;
注意:
{src}对应安装包所在目录,如果安装包存放在光盘、写保护U盘等只读介质中,会出现缓存写入失败的问题,建议增加目录可写判断,如果{src}不可写,将缓存路径切换到{localappdata}下的软件专属目录即可。
方案选型对比
- 修改下载临时目录方案:不推荐。IDP的临时下载路径属于内部管控参数,没有公开修改接口,硬改内部变量会存在版本兼容问题,后续升级插件极易失效;且下载过程中如果安装流程中断,会在缓存目录留下损坏的不完整文件,下次启动需要额外增加文件校验逻辑,实现复杂度高。
- 下载后移动文件方案:推荐。仅需绑定官方公开的回调事件,代码量少兼容性强,同分区移动无额外磁盘开销,完全规避双倍空间占用问题,后续维护成本极低。
后续动态磁盘空间提示实现
等即时移动逻辑调通后,你可以在添加每个下载项之前,调用DownloadTemporaryFileSize拉取对应远程文件的大小,累加所有待下载文件的总大小后,动态更新ExtraDiskSpaceRequired配置即可。由于单文件下完就会被移走,临时目录不会堆积大文件,磁盘空间计算只需要统计缓存目录的最终占用,逻辑不会冲突。
内容的提问来源于stack exchange,提问作者orecchione bruno
相关产品推荐
相关产品推荐

