c++用libcurl实现断点续传需先head校验accept-ranges,再设curlopt_range或curlopt_resume_from发起range请求,响应206时以"ab"模式追加写入,否则全量重下,并通过.meta文件校验url与etag确保续传安全。

如何用 libcurl 实现断点续传下载
libcurl 是最实用的选择,它原生支持 Range 请求和 206 Partial Content 响应,不用自己拼 HTTP 头或解析状态码。关键不是“能不能”,而是怎么正确设置选项避免覆盖已有文件或忽略服务端不支持的情况。
- 必须用
CURLOPT_RESUME_FROM或CURLOPT_RANGE,二者选一:前者适合已知已下载字节数(如从本地文件 size 推算),后者更直观(如"1024-"表示从第 1024 字节起) - 务必检查服务端是否真返回
206:有些服务器对Range请求静默降级为200,此时会重传全部内容——需在CURLOPT_HEADERFUNCTION回调里捕获HTTP/1.1 206或Content-Range头确认 - 写文件时用
fopen(..., "ab")(追加模式),而不是"wb";否则续传会清空已有数据
如何判断本地文件是否可续传
不能只看文件是否存在,得验证它是否是同一 URL 的中途产物、且服务端支持断点。常见错误是把一个完整下载的文件当成断点起点,结果请求 Range: 1000- 却收到 200 OK,导致文件损坏。
- 推荐做法:下载前先 HEAD 请求目标 URL,检查响应头是否含
Accept-Ranges: bytes;若无,直接全量下载 - 本地文件需满足两个条件才启用续传:文件存在 且
stat().st_size > 0(非空) - 可选增强:把原始 URL 和 ETag 存入同名
.meta文件,续传前比对,避免 URL 相同但资源已更新
为什么 CURLOPT_RESUME_FROM 有时无效
这个选项看似简单,实际依赖服务端配合。libcurl 内部只是自动加 Range 头,如果服务端无视或返回 200,CURLOPT_RESUME_FROM 就形同虚设。
- 典型表现:设置
CURLOPT_RESUME_FROM为 1024,但回调函数收到的数据从第 0 字节开始——说明服务端没响应206 - 调试方法:开启
CURLOPT_VERBOSE,观察 curl 输出里是否出现> Range: bytes=1024-和 - 某些 CDN(如 Cloudflare)默认禁用
Range,需在源站配置显式开启;Nginx 需确认accept_ranges on;已启用
简易实现中容易漏掉的错误处理
断点续传不是“多加个参数就完事”,核心在于失败后的状态回退和重试逻辑。很多 demo 忽略了网络中断后如何安全恢复。
- 下载中途失败时,不要删除已写入的文件——保留它才能下次续传;但要确保文件末尾没写入脏数据(可用
ftruncate()在出错时截断到最后校验位置) - HTTP 状态码不是唯一依据:
503或连接超时需重试,但416 Requested Range Not Satisfiable意味着本地记录的 offset 错了,应清空文件重新开始 - libcurl 默认不校验 Content-Length 是否匹配 Range,建议在 write callback 里累计写入字节数,若远小于预期(如差几百 KB),可能是服务端提前关闭连接,应视为失败
真正麻烦的从来不是第一次下载,而是第 3 次断在 98% 时——这时候磁盘空间、文件锁、服务端临时限流,任何一个环节没兜住,就会前功尽弃。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











