HTTP 断点续传是怎么实现的?
简化版
断点续传靠 HTTP 的 Range 机制:客户端在请求头带 Range: bytes=开始-结束,只要这一段;服务器返回 206 Partial Content 和这段数据(配 Content-Range 说明范围)。下载中断后,客户端记住已下载到哪,续传时请求剩下的那段即可。前提是服务器支持——它会在响应里用 Accept-Ranges: bytes 声明支持范围请求。
详细版
断点续传的交互:
① 客户端探测是否支持(或首次请求响应里就带):
响应头:Accept-Ranges: bytes ← 服务器声明支持范围请求
② 下载到 5000 字节时断了,续传请求剩余部分:
请求头:Range: bytes=5000- ← 从第 5000 字节要到结尾
③ 服务器返回:
HTTP/1.1 206 Partial Content
Content-Range: bytes 5000-9999/10000 ← 本次是 5000~9999,总共 10000 字节
Content-Length: 5000
<这一段的数据>
关键要素:
Range请求头:bytes=start-end,指定要哪一段(bytes=5000-表示 5000 到结尾);206 Partial Content:服务器返回部分内容的状态码(不是 200);Content-Range:说明本次返回的是「哪一段 / 总大小」;Accept-Ranges: bytes:服务器声明支持按字节范围请求(不支持则整体返回 200)。
完整版教学
一、断点续传解决什么
下载大文件(视频、安装包)时,网络断了或手动暂停——如果每次都从头下,既慢又浪费流量。断点续传让下载能从上次中断的位置接着下,而不是重来。
它的核心思路很朴素:把大文件按字节范围切分,客户端只请求自己还缺的那一段。已经下好的部分不用再传。这也是多线程下载工具(把文件分成多段并发下载)和视频「拖动进度条秒开」(跳到某个字节位置开始播)的底层原理。
二、Range:按字节要「一段」
普通 HTTP 请求要的是整个资源。Range 请求头让客户端只要其中一段:
Range: bytes=0-499:要前 500 字节;Range: bytes=5000-:从第 5000 字节要到结尾(续传就用这个);Range: bytes=-500:要最后 500 字节;Range: bytes=0-499,1000-1499:一次要多段(多重范围,响应用 multipart)。
服务器支持的话,返回 206 和对应字节段,并用 Content-Range: bytes 5000-9999/10000 明确告诉客户端「这是第 5000~9999 字节,文件总共 10000 字节」。
三、206 和 200 的区别
- 200 OK:返回完整资源;
- 206 Partial Content:返回部分资源(响应了 Range 请求)。
客户端看到 206 就知道拿到的是一段、不是全部,配合 Content-Range 把这段拼到正确位置。如果服务器不支持 Range,会忽略 Range 头、直接返回 200 + 完整内容——客户端据此判断「这个服务器不支持断点续传」。
四、怎么保证续传的是「同一个文件」
有个隐患:续传时,万一服务器上的文件已经变了(比如更新了),你把新文件的一段拼到旧文件后面,就拼出个损坏的文件。
为防止这个,断点续传常配合校验:
- 客户端在续传请求里带
If-Range: <ETag 或 Last-Modified>——「如果文件还是这个版本,就给我 Range;如果变了,就返回完整的新文件(200)」; - 服务器比对:文件没变 → 206 给续传段;文件变了 → 200 返回整个新文件,客户端重新下载。
这样保证续传拼接的一定是同一个版本的文件。
五、常见误区
- ❌ 以为所有服务器都支持断点续传——要服务器支持 Range 并返回
Accept-Ranges: bytes,不支持就整体返回 200。 - ❌ 把 206 当异常——它是「部分内容」的正常成功响应,不是错误。
- ❌ 续传不校验文件版本——文件变了会拼出损坏文件,应配
If-Range校验。 - ❌ 以为 Range 只能续传——它也用于多线程下载、视频拖动进度(按字节定位播放)。
六、常见误区与追问
| 考点 | 正确口径 |
|---|---|
| Range | 客户端请求某个字节区间 |
| 206 | 服务器返回部分内容 |
| Content-Range | 说明返回区间和总长度 |
| If-Range | 确认资源未变再续传 |
Range: bytes=1000-1999
HTTP/1.1 206 Partial Content
Content-Range: bytes 1000-1999/5000
断点续传不是从“行”或“包”继续,而是按资源字节偏移继续请求。
- 误区:断点续传靠 TCP 自动完成。 TCP 只负责连接内字节流可靠传输,断点续传是 HTTP 应用层 Range 机制。
- 误区:返回 200 也表示续传成功。 续传成功通常是 206 Partial Content;200 可能表示服务器返回完整文件。
- 误区:文件变化后还能按旧偏移续传。 资源变化会导致偏移对应内容不同,需要 ETag/Last-Modified 和 If-Range 校验。
- 追问:服务器不支持 Range 怎么办? 会返回完整内容或忽略 Range,客户端只能重新下载。
- 追问:多线程下载怎么做? 客户端把文件分成多个字节区间并发请求,最后按偏移合并。
- 追问:416 状态码表示什么? 请求的 Range 不合法或超出资源范围。
七、加强记忆
HTTP 断点续传靠 Range 机制:客户端请求头带 Range: bytes=start-,服务器返回 206 Partial Content + Content-Range(说明本段/总大小);服务器用 Accept-Ranges: bytes 声明支持。续传时配 If-Range 校验文件版本,防止文件变了拼出损坏文件。它也是多线程下载和视频拖动进度的底层原理。