断点续传必须由客户端主动发送range请求头,格式为“range: bytes=start-”或“range: bytes=start-end”,服务端仅在返回206 partial content且含合法content-range时才真正支持续传;若返回200或缺失content-range,应中止续传并重下。

断点续传协议依赖的HTTP Range头怎么发
客户端必须主动声明支持断点续传,否则服务器不会返回分段内容。关键在于发送带 Range 请求头的 GET 请求,格式为 Range: bytes=1024-(从第1024字节开始)或 Range: bytes=1024-2047(指定区间)。服务端响应状态码必须是 206 Partial Content,而非 200 OK;如果返回 200,说明服务器不支持或没识别该头,此时不能继续续传逻辑。
常见错误:用 curl -H "Range: bytes=1000-" ... 测试时返回 200,大概率是 Nginx/Apache 默认未启用静态文件分段支持,需显式配置 add_header Accept-Ranges bytes;(Nginx)或确认 Apache 的 mod_headers 和范围支持已开启。
下载状态机需要维护哪几个核心字段
状态机不是靠 switch-case 堆逻辑,而是靠一组不可分割的原子状态变量驱动行为。必须持久化以下字段到本地(如 JSON 文件或 SQLite):
-
url:原始下载地址(用于重试和重定向跟踪) -
local_path:目标文件路径(注意含 .part 后缀,避免被其他程序误读) -
offset:已成功写入的字节数(即下次Range起始位置) -
total_size:从Content-Range响应头解析出的总长度(如bytes 1024-2047/1048576中的1048576),若首次请求无此头,设为-1表示未知 -
etag或last_modified:用于校验文件一致性,重启后比对服务端响应头,防止源文件被篡改或替换
漏存 offset 或未校验 etag 是导致“续传后文件损坏”最常见原因——你以为接着下,其实服务端文件早已更新。
libcurl 多线程下如何安全更新 offset 并避免写冲突
libcurl 本身不保证回调函数(WriteCallback)线程安全,尤其在启用 CURLOPT_HEADERFUNCTION + CURLOPT_WRITEFUNCTION 双回调时,二者可能并发执行。直接在回调里更新全局 offset 变量会丢字节。
正确做法:
- 用
std::atomic_long存储offset,并在每次WriteCallback写入成功后原子累加实际字节数(nbytes参数) - 禁用
CURLOPT_HEADERFUNCTION,改用CURLOPT_HEADERDATA+ 自定义解析器,在单次完整响应后统一提取Content-Range和ETag - 每完成一个
Range块(例如 1MB),调用一次fsync()+ 写入临时状态文件,而不是等全部下载完再落盘
示例片段:
size_t write_cb(void* ptr, size_t size, size_t nmemb, void* userdata) {
auto& state = *static_cast<downloadstate>(userdata);
size_t written = fwrite(ptr, size, nmemb, state.file);
state.offset.fetch_add(written, std::memory_order_relaxed);
return written;
}</downloadstate>
如何判断续传是否真正生效而非退化为全量重下
仅检查 HTTP 状态码是不够的。必须同时验证三点:
- 响应头包含
Content-Range字段(libcurl 用CURLOPT_HEADERFUNCTION捕获) -
Content-Range中的起始偏移等于你请求的Range起始值(防止服务端忽略并返回全文) - 响应体长度等于
Content-Range中计算出的区间长度(例如bytes 1024-2047/1048576应返回 1024 字节)
任一条件失败,应中止续传流程,清空临时文件,走完整下载路径——强行续传只会让文件头尾错位。很多 CDN(如 Cloudflare)在缓存未命中时会静默降级为 200,但不报错,这就是最隐蔽的坑。
实际开发中,offset 和 Content-Range 的双重校验比任何日志打印都管用;状态机复杂度不在状态数量,而在这些边界条件的覆盖密度。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











