HTTP Range 请求如何实现断点续传?206、Content-Range 和 If-Range 有什么作用?
下面是一段教学模拟,不是真实面试记录。
🧑💻 面试官:下载一半断了,怎样继续?
🙋♂️ 我:记住长度,Range 请求剩余字节,再追加。
🧑💻 面试官:服务器文件换了一版,还能追加吗?
🙋♂️ 我:要校验是不是同一份文件。
🧑💻 面试官:如果忽略 Range 返回 200 和完整文件,你也直接追加吗?
断点续传要确认「下一个字节在哪里」,也要确认「属于同一份文件表示」。
面试速答(60 秒版)
Range 允许请求资源的一段内容。字节从零开始,已保存前 1000 字节,可以请求 bytes=1000-。
服务器接受时通常返回 206,用 Content-Range 说明实际区间与总长。客户端应核对起点和长度,再写入正确位置。
续传还要验证版本。可以用强 ETag 配合 If-Range:版本符合时返回部分内容,不符合时可能返回整个资源的 200 响应,不能直接追加到旧文件。
范围不可满足时可能收到 416。实现要区分状态,并保持编码与表示一致,不能只看是否收到一段字节。

图中假设文件一共 2000 字节,并且续传请求带上了版本校验条件。版本改变时返回完整文件,不是 Range 自己检测到了变化,而是后面要讲的 If-Range 条件没有匹配。
知识点详解:从偏移 1000 继续,怎样保证没有拼错?
偏移从零开始,末端包含在区间内
假设文件长 2000 字节,已保存 0 到 999。可以发送:
Range: bytes=1000-
接受后示意响应是:
HTTP/1.1 206 Partial Content
Content-Range: bytes 1000-1999/2000
Content-Length: 1000
长度为 1999 − 1000 + 1,是 1000 字节。这里 Content-Length 描述响应体,不是整份文件长度。Range 指南
收到 206,也要检查区间
核对 Content-Range 起点与预期位置、实际收到的长度,再写入。
如果中途再断,保存的是实际可靠落盘部分,不是请求计划的全部长度。
并发多区间还要避免重复、空洞和错序,不能把最后一个请求成功当成全部完成。本文只讨论单区间基础机制。
If-Range 将续传与版本绑定
首次取得强 ETag “v1”,后续可以发送:
Range: bytes=1000-
If-Range: "v1"
版本符合时可返回范围;不符合时可以忽略范围返回完整资源。
因此,206 按核验过的位置写入;200 当成完整响应处理,必要时重新开始或替换,不能追加。否则旧版前半段加新版完整内容,拼出的不是任何一个正确文件。If-Range 文档

416 和不支持范围,不能当成成功
偏移超出资源时,可能返回 416,并通过 Content-Range: bytes */2000 表达当前长度。
原因可能是本地记录错误或资源改变。先核对版本和长度,不要直接宣布已完成。
Accept-Ranges 能提供支持提示,但实际还可能收到 200。客户端要按响应处理,不能只根据首次头判断未来所有请求。
同一 URL 不等于同一字节表示
压缩等编码会改变字节序列。记录了压缩表示的偏移,就不能拿它直接续写解压后的内容。
认证、重定向和动态生成也可能影响表示。可靠实现应确认验证器、长度、编码,最后按需要校验完整性。
这些是 HTTP 行为,不必把头示例机械复制成 TypeScript 和 Python。不同语言客户端都需要相同的验证分支。
面试官继续追问
URL 一样,可以证明文件没变吗?
不能。内容可以替换,也可能按请求条件生成。需要版本验证和响应信息。
本地大小等于总长,就一定正确吗?
不够。错误拼接也可能得到相同长度,重要内容还应进行完整性校验。
不支持 Range 怎么办?
退回完整下载并正确处理旧文件,不要假装完成续传,也不要把 200 内容继续追加。
面试速记卡
- Range:指定区间,字节偏移从 0 开始。
- 206:检查 Content-Range 与实际长度。
- If-Range:绑定版本,教学例子使用强 ETag。
- 200:可能是完整回退,不能追加到旧内容。
- 416:范围不可满足,检查版本、长度与本地记录。
公司面试真题
这道题暂未收录可核验的公司真题来源。你可以先阅读本文解析,或浏览已收录的公司面试真题。
浏览公司面试真题 →