反向代理支持断点续传的关键是端到端协同:必须关闭proxy_buffering和proxy_cache、透传Range/If-Range头、禁用gzip压缩,并确保后端真实支持206响应且链路中无中间件拦截。

要让反向代理链路完整支持断点续传(即 HTTP Range 请求),关键不是简单地透传 Range 请求头,而是确保整个链路——从客户端、Nginx 代理层,到后端源站(如静态文件服务、对象存储网关或应用服务器)——都正确识别、处理并响应 206 Partial Content。单独设置 proxy_set_header Range $http_range; 是必要但不充分的步骤。
必须开启 proxy_buffering off 并禁用缓存干扰
Nginx 默认启用缓冲(proxy_buffering on),这会导致它将整个响应体读取完毕后再转发给客户端。一旦后端返回的是 206 响应,Nginx 缓冲机制可能截断或误判分块内容,破坏 Range 的语义。因此需显式关闭:
-
proxy_buffering off;—— 强制流式透传,避免缓冲干扰部分响应 -
proxy_cache off;或精确配置缓存策略:默认proxy_cache会拒绝缓存206响应,但若自定义了 cache key 或忽略状态码,可能意外缓存不完整响应,务必确认未启用或已排除206 - 禁用 gzip 压缩:
gzip off;(或至少对带Range的请求禁用),因为压缩会改变原始字节范围,使客户端无法按原始 offset 续传
正确透传 Range 和 If-Range 头,并保留原始请求上下文
仅透传 Range 不够,还需同步传递校验头,否则后端无法安全判断是否可续传:
-
proxy_set_header Range $http_range;—— 透传客户端 Range 请求头 -
proxy_set_header If-Range $http_if_range;—— 若客户端携带此头(通常含 ETag 或 Last-Modified),后端需据此决定是否接受 Range 请求 - 避免覆盖或删除其他关键头:如
Accept-Ranges: bytes应由后端返回,Nginx 不应添加或修改;若后端未返回,说明它本身不支持 Range,此时 Nginx 无法“补救”
确保后端真实支持 Range,且不被中间层拦截
Nginx 只是中转者,最终能力取决于后端。常见陷阱包括:
- 后端是 Python Flask/FastAPI 等框架时,需使用支持 Range 的静态文件中间件(如 Flask 的
send_file默认支持,但需确保未包裹在不支持流式响应的装饰器中) - 后端为 Nginx 自身(二级代理或本地文件服务):确认其
accept_ranges on;已启用,且文件系统支持(如 ext4/xfs 没问题,某些网络文件系统或只读挂载可能限制) - CDN 或 WAF 在 Nginx 前置:它们可能主动剥离
Range头或强制回源全量请求,需检查其文档并开启“Range 请求透传”选项(如 Cloudflare 的 “Origin Rules” 中启用 “Cache Based on Request Headers: Range”)
验证与调试要点
部署后务必实测,不能仅看配置:
- 用
curl -v -H "Range: bytes=100-199" https://yoursite/file.zip检查响应状态是否为206,Content-Range是否匹配,Content-Length是否为实际字节数(100) - 对比直接访问后端(绕过 Nginx)的结果,若直连正常而代理异常,问题一定出在 Nginx 配置或前置链路
- 查看 Nginx error log:搜索
upstream sent invalid header或range not satisfiable,常提示后端返回了416但 Nginx 未能正确透传 - 用
tcpdump或 Wireshark 抓包,确认客户端发出的 Range 头确实到达后端,且后端返回的206响应原样抵达客户端
不复杂但容易忽略:断点续传依赖端到端协作,Nginx 的 proxy_set_header Range 只是起点,真正起作用的是缓冲控制、头透传完整性、后端能力及链路中每个环节的兼容性。


















