nginx 缓存与断点续传天然冲突,需绕过缓存处理 range 请求:通过 proxy_cache_bypass $http_range 和 proxy_no_cache $http_range 确保 206 响应不被缓存,静态文件则依赖原生 range 模块,文件本体不应缓存。

Nginx 缓存本身与断点续传(Range 请求)存在天然冲突:标准 proxy_cache 或 fastcgi_cache 会把整个响应(如 200 OK)缓存下来,而断点续传依赖的是每次返回不同的 206 Partial Content 响应。一旦缓存了 200 响应,后续 Range 请求就可能被错误地返回完整文件或 416 错误。
所以不是“用缓存支持断点续传”,而是“避免缓存破坏断点续传”。关键在于让 Nginx 正确绕过缓存处理 Range 请求,并保障 206 响应不被缓存、不被合并。
确保 Range 请求不走缓存路径
Nginx 默认对含 Range 头的请求会自动跳过 proxy_cache(从 1.7.7 起),但必须显式配置防误触发:
location /downloads/ {
proxy_pass https://backend;
# 强制对 Range 请求绕过缓存
proxy_cache_bypass $http_range;
proxy_no_cache $http_range;
# 同时禁止缓存 206 响应(即使意外进入缓存流程)
proxy_cache_valid 206 1m; # 可设极短时间,或直接不缓存
# 更稳妥做法:完全禁用 206 缓存
proxy_ignore_headers Cache-Control Expires Set-Cookie;
}
✅
proxy_cache_bypass $http_range:只要请求带Range头,就不查缓存,直接转发。
✅proxy_no_cache $http_range:即使后端返回了Cache-Control: public,也强制不缓存该响应。
❌ 不要写proxy_cache_valid 200 206 1h—— 这会让 206 被缓存,导致后续请求返回错误字节范围。
静态大文件场景(无代理,直接 serve)
若 Nginx 直接提供 ZIP/MP4 等静态文件(root / alias),它不使用 proxy_cache,也不需要配置缓存——断点续传由原生 ngx_http_range_module 处理,天然支持 206。此时只需:
- 确保没启用
slice指令干扰(除非你明确要做动态切片); - 避免
gzip on对大文件生效(加gzip_disable "range";); - 显式声明头(可选但推荐):
add_header Accept-Ranges bytes;
缓存策略应聚焦「元数据」而非「文件体」
真正适合缓存的是:
- 文件列表接口(如
/api/files?name=xxx)→ 返回 JSON,可缓存 5–30 分钟; - 文件校验信息(ETag、Content-MD5)→ 用于客户端判断是否需重传;
- 重定向链接(如预签名 URL)→ 缓存 1–5 分钟即可。
而文件本体(尤其是 >10MB 的二进制流)不应被 Nginx 缓存——既增加磁盘压力,又极易因缓存污染导致 Range 错误。
验证是否生效
用 curl 测试真实行为:
# 应返回 206 + Content-Range,且无 X-Proxy-Cache 或 Age 头 curl -I -H "Range: bytes=0-1023" https://example.com/large.zip # 对比无 Range 请求(应为 200,可缓存) curl -I https://example.com/large.zip
若 Range 请求返回了 X-Proxy-Cache: HIT 或 Age: 120,说明缓存未正确绕过,需检查 proxy_cache_bypass 是否生效、变量名是否拼错(如 $http_range 不是 $range)。
不复杂但容易忽略。











