Watch at Ease看见世界,读懂生活。

科技 · 实用指南

curl 断点续传后文件损坏?用强 ETag 绑定每个字节范围

字节偏移不是内容身份。用 Range 与 If-Range,仅追加精确的 206 响应;200 时从零重启,并在原子替换前验证。

curl 断点续传后文件损坏?用强 ETag 绑定每个字节范围
原创示意图: 200 与 206 的安全写入分支。 Watch at Ease

安全续传要求每个追加字节都来自同一个 HTTP 表示。curl -C - 使用的本地长度只是偏移量,不是内容身份。

把部分文件绑定到最终 URL 与强 ETag,用 Range 加 If-Range 请求剩余内容,并让 206 或 200 决定追加还是全新替换,最后验证后再原子改名。

1. 本地长度只是偏移,不是身份

curl -C - 会检查目标长度并请求后续字节,但无法证明远端仍是同一版本。把最终 URL、强 ETag、本地长度、预期总长和发布方摘要保存在与单一输出绑定的旁车记录中。

使用专用 .part 文件;不要让多个 URL 共用一个 ETag 状态文件。

2. 续传前要求强验证器

发送 Range: bytes=N- 和带已存强 ETag 的 If-Range。RFC 9110 不允许在 If-Range 中使用弱 ETag;缺少强验证器时应从零下载到新文件。

--etag-compare 发送 If-None-Match,它不是 If-Range;包装脚本应显式发送 If-Range 并捕获响应头。

3. 根据响应选择写入模式

仅当状态为 206、Content-Range 从 N 开始、总长合理且验证器一致时追加。先把响应写到临时尾文件,验证头部后再合并。

If-Range 失配会得到完整 200,必须写入新的完整临时文件,绝不能追加;416 需要核对长度、总长与验证器。

4. 只重试传输故障

只对已分类的暂时传输故障限次退避重试。认证失败、重定向变化、缺少验证器、异常状态、错误 Content-Range 或摘要不符都应停止或干净重启。

curl 8.5.0 夹具证明:无验证器的变化对象返回 206 并产生混合文件;旧 ETag 的 If-Range 返回 200 并安全替换;未变化对象返回 206 且摘要一致。

5. 验证后再原子晋升

完成后优先核对发布方摘要;否则至少核对总长与相同强 ETag,并承认长度不是完整性证明。可用时再运行归档或应用格式检查。

验收后才在同一文件系统中原子改名。保留旁车和日志,隔离不可验证或已经混合的部分文件。

字节偏移不是内容身份。用 Range 与 If-Range,仅追加精确的 206 响应;200 时从零重启,并在原子替换前验证。
原创示意图: 远端身份、部分文件与验收证据保持绑定。 Watch at Ease