直接回答
可恢复下载不只是超时后重试一次请求。客户端必须知道正在下载哪一个制品、部分字节存放在哪、服务器的 Range 响应代表什么、如何发现远端文件变化、怎样校准进度,以及何时临时文件才可以转为最终文件。Cove 当前下载器源码记录了存储预检、临时文件写入、HTTP Range 恢复请求、字节进度、部分连接故障时配置的镜像、摘要存在时可选 SHA-256 校验以及最终重命名。这些源码事实描述当前实现,并不能证明公开 APK 已提供,也不能保证每台服务器都遵守恢复语义。 要区分四种状态:下载已启动、已有部分字节、响应传输完成、文件已经验证并放置。超时后遗留的部分文件,如果远端内容变了,就不能安全追加。若协议和服务器提供 ETag 或 Last-Modified 等验证器,客户端应保留并比较响应元数据;无法确认身份时,应从新临时文件重启,不要拼接来源不明的字节。服务器忽略 Range 时可能返回完整 200 响应;若把它追加到已有部分文件,最终制品会损坏。状态码、Content-Range、预期长度和校验摘要都应作为验证输入,不能只看进度条。 每个模型版本使用唯一临时路径,下载更新时不要覆盖当前可用模型。进程停止后只持久保存恢复所必需的制品标识和传输元数据;重启时先将实际临时文件长度与服务器响应对账。仅在预期总长度已知且一致时显示百分比。若来源未提供可信摘要,应明确说明完整性尚未完全验证;长度只能发现部分截断,不能证明发布者身份。不能因为 HTTP body 结束就静默标记“就绪”。 生命周期机制应按产品行为选择。用户可见前台下载和可延迟持久任务拥有不同的用户控制和平台规则。WorkManager 可以在约束下调度持久工作,但不承诺网络和进程在所有情形下持续不中断。进度要可持久化,Worker 要幂等;取消、重试和失败应对用户可见。避免多个 Worker 同时写同一制品路径:按版本只允许一个传输所有者,其他观察者可以订阅同一任务状态。 最终重命名前,依据可用元数据验证接收文件与预期制品一致。尽可能在同一文件系统原子放置,重新打开最终路径,并让运行时执行加载检查后再显示“可用”。验证失败时保留之前的好文件,并说明新文件尚未安装。镜像只是传输路径,不能证明发布者身份。 测试要覆盖多个中断点:响应头前、中途传输、最后一个字节后但校验前、重命名时和运行时加载时;同时覆盖服务器支持 Range、忽略 Range、实体改变或提前断开等情况。日志不能写入认证令牌和签名 URL。实施时先固定制品与临时路径;恢复时校验状态码、Content-Range、实体身份和文件长度;重建任务进度并防止并发写入;校验长度与可信摘要后再原子放置、重开和加载;失败时保留旧制品和用户数据。安全下载流程证明的是每个状态转换,不是分发或设备兼容承诺。
火车上大型模型下载中断
用户在按流量计费的移动网络上下载模型,信号在中途消失,之后应用进程被重建。用户希望继续下载,而不是重新开始或打开损坏文件。
决策
仅在制品身份和字节范围元数据匹配时续传;否则建立全新临时文件并保留之前可用模型。
预期结果
界面如实呈现已保存进度,验证完整制品,并在无法恢复时指出失败阶段。
需要收集的证据
只有将以下证据与同一模型文件和测试运行关联起来,结论才可复核:
- 不可变制品标识和临时路径
- Range 响应与验证器
- 完整性、原子放置和运行时加载结果
收到完整字节流还不够;最终落盘、完整性、运行时加载和恢复路径也必须验证。
实施流程
- 创建按制品隔离的临时传输. 用不可变模型版本为临时文件和 Worker 建键。保存预期长度、可选可信摘要和响应验证器;普通日志不得写授权令牌或带签名的查询参数。
- 验证续传响应. 追加前检查状态码、Content-Range、总长度、实体标签等验证器以及当前临时文件长度。若无法证明远端表示与部分字节相同,就安全重启。
- 进程重建后对账进度. 恢复时比较持久进度、实际文件长度和服务器响应。设置唯一任务策略,避免第二个 Worker 同时写入同一制品版本。
- 最终放置前完成验证. 在摘要存在时校验可信摘要及总长度,尽可能原子重命名临时文件,重新打开并请求运行时加载检查。任何阶段失败都保留旧制品。
让每个阶段的状态都可观察。失败信息应指出阶段、模型、运行时和恢复动作,同时避免记录用户私密内容。
验收标准
- 只有验证远端表示未变化后才续传,不会拼接身份不明的字节。
- 同一模型版本仅有一个写入者,进程重建后进度一致。
- 完整性检查和运行时加载通过前,界面不会将模型标为就绪。
决策对照表
| 维度 | 选择或证据 | 解读方式 |
|---|---|---|
| 从零重新下载 | 写入新临时文件 | 身份无法安全确认时可用,但会丢弃部分传输进度。 |
| HTTP Range 续传 | 验证响应身份后追加 | 验证器和 Content-Range 能证明是同一制品时可复用部分字节。 |
| HTTP 结束即标记就绪 | 只检查传输状态 | 不充分;完整性、文件放置和运行时加载仍需单独检查。 |
需要避免的失败模式
- 把完整响应追加到已有部分文件
- 用文件长度代替真实性证明
- HTTP 结束后立即标记模型可用
还要避免静默回退、版本未固定、缺少取消处理,以及把不同配置的结果混在一起下结论。失败运行也应与成功记录一并保存。
最小复现记录
| 层级 | 记录内容 |
|---|---|
| 设备 | 厂商、型号、芯片、内存档位、操作系统版本 |
| 软件 | 应用版本和 Git 提交号 |
| 模型 | 系列、变体、版本、格式、文件长度、摘要、量化方式 |
| 运行时 | 名称、版本、请求后端及实际后端证据 |
| 工作负载 | 样例版本、输入摘要、提示词摘要、输出策略 |
| 结果 | 完成、失败、取消、回退及保护隐私的诊断信息 |
发布检查表
- ☐ 主要搜索问题已回答,且没有未经支持的数字。
- ☐ 所有模型文件和运行时版本均已固定。
- ☐ 代表性任务和失败处理策略均有说明。
- ☐ 生命周期、取消、清理和回退均已测试。
- ☐ 用户内容与网络边界均有说明。
- ☐ 结论只适用于被记录的配置。
- ☐ 新增测试结果时链接到原始方法或证据。
来源与相关证据
- Android persistent background work
- Cove ModelDownloader 源码
- Android Developers — 持久后台工作
- IETF HTTP 语义与范围请求
中文部署与排错专题见。奇连 AI 端侧专题。
常见问题
HTTP Range 能保证下载正确恢复吗?
不能。客户端还要核验服务器响应和文件身份。如果服务器忽略范围或实体已变化,追加可能损坏文件;无法对账时应安全重启。
字节数量完整能证明模型是真实可信的吗?
不能。长度检查能发现部分截断,但无法证明发布者身份。如果来源提供可信摘要或签名元数据,应进行验证;没有时要明确说明完整性仍有限。
WorkManager 能保证下载不会停止吗?
不能。它提供受约束的持久工作机制,不承诺网络和进程从不中断。实现时要有持久进度、幂等写入、取消和重试状态。