X-Accel-Redirect 是实现权限与传输分离的关键机制,需严格配置 internal location、正确使用 alias/root、传递内部 URI 而非真实路径,并显式设置 Content-Type、Content-Disposition 等响应头。

X-Accel-Redirect 不是“让 Nginx 帮你发文件”那么简单,而是把「权限判断交给应用、文件传输交给 Nginx」的明确分工。它能真正把 PHP/Python/Java 进程从 I/O 中解放出来,但配置错一个字符,就返回空响应或 404。
location 配置必须带 internal 且路径对齐
这是最常踩的坑:Nginx 拒绝响应却没报错,浏览器静默失败。
-
internal是硬性要求——没有它,外部请求可直访该 location,完全绕过你的权限逻辑 -
root和alias行为完全不同:root会拼接整个请求路径,alias则替换前缀;比如location /protected/ { alias /data/files/; },那么X-Accel-Redirect: /protected/cat.jpg对应真实路径是/data/files/cat.jpg;而用root时,同样 header 会指向/data/files/protected/cat.jpg - Windows 下路径注意 Cygwin 风格:
/cygdrive/d/path,不是D:/path;Linux 下绝对路径必须以/开头,且 Nginx worker 进程要有读权限
X-Accel-Redirect 头必须是内部 URI,不能是真实文件路径
后端代码里传的不是 /data/files/report.pdf,而是你定义好的、带 internal 保护的那个 location 路径。
- 错误写法:
header('X-Accel-Redirect: /data/files/report.pdf');→ Nginx 忽略该 header,继续输出空 body - 正确写法:
header('X-Accel-Redirect: /protected/report.pdf');,前提是 Nginx 有对应location /protected/ { internal; alias /data/files/; } - 路径中不能含
..或符号链接跳转,Nginx 默认禁止路径穿越;如需支持子目录,确保 location 前缀足够精确(例如用location ^~ /protected/)
必须显式设置 Content-Type 和 Content-Disposition
Nginx 不会继承后端设的 Content-Type,也不会自动加 attachment;不设就按 text/plain 渲染,用户看到乱码或直接在浏览器打开。
-
Content-Type要匹配文件实际类型,PDF 用application/pdf,ZIP 用application/zip,通用二进制用application/octet-stream -
Content-Disposition推荐用双格式写法,兼顾旧浏览器:attachment; filename="file.zip"; filename*=utf-8''file.zip - 务必加
Cache-Control: no-transform,防止 CDN 或代理篡改响应体(尤其影响X-Accel-Redirect生效)
限速和缓冲控制要靠配套 header,不是靠 PHP sleep
想限制下载速度?别在 PHP 层做流控——那只是假限速,Nginx 仍会全量读取并堆积 buffer。
- 用
X-Accel-Limit-Rate: 512000(单位字节/秒),值为 0 表示不限速 - 加
X-Accel-Buffering: no可禁用 Nginx 缓冲,适合实时日志或极敏感场景;默认yes更稳 - 若需断点续传,确保不设
Accept-Ranges: none;Nginx 默认支持Range请求,但一旦加了这个 header 就彻底关掉
open() "/xxx" failed (2: No such file) 类提示。



















