根本原因是Nginx未将.php请求交给PHP-FPM处理,而是当作静态文件直接返回,常见于location ~ .php$未启用、fastcgi_pass端口不匹配、SCRIPT_FILENAME路径拼接错误或PHP-FPM未运行。

为什么Nginx访问PHP文件会直接下载而不是执行
根本原因是Nginx没把 .php 请求交给PHP-FPM处理,而是当成静态文件直接返回了原始代码。常见于Windows下phpEnv环境——location ~ \.php$ 块被注释、fastcgi_pass 指向错误端口、或 fastcgi_param SCRIPT_FILENAME 路径拼接失败。
检查点:
• 打开 nginx.conf,确认 location ~ \.php$ 段落已取消注释
• fastcgi_pass 必须匹配PHP-FPM监听方式:Windows下多为 127.0.0.1:9000(不是 unix:/...)
• fastcgi_param SCRIPT_FILENAME 必须用 $document_root$fastcgi_script_name,不能硬写路径或漏掉 $document_root
• PHP-FPM服务必须正在运行(php-cgi.exe -b 127.0.0.1:9000 或通过服务管理器启动)
phpEnv中Nginx配置PHP文件下载的两种方式
要让PHP脚本触发文件下载(比如生成报表后导出Excel),核心是PHP用 header() 控制响应行为,Nginx只负责透传。但若想绕过PHP读取文件再输出(避免内存暴涨),可启用 X-Accel-Redirect。
推荐做法:
• 在 nginx.conf 的 server 块内添加:
location /protected/ {<br> internal;<br> alias E:/protected_files/;<br>}• PHP中调用:
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');<br>header('Content-Disposition: attachment; filename="report.xlsx"');<br>header('X-Accel-Redirect: /protected/report.xlsx');• 注意:
alias 结尾不加斜杠,X-Accel-Redirect 路径必须以 /protected/ 开头,且不能暴露真实磁盘路径• 禁用
fastcgi_buffering off 不必要——X-Accel-Redirect 由Nginx内核直接处理,不经过PHP缓冲
立即学习“PHP免费学习笔记(深入)”;
PHP中用header设置下载头时最容易踩的坑
header() 失效不是因为写法错,而是输出时机不对。phpEnv在Windows下尤其敏感:
• 文件开头存在BOM(哪怕编辑器显示为空白)→ 导致 header() 调用前已有隐式输出
• php.ini 中 output_buffering = On 且未显式 ob_end_clean() → 缓冲区残留内容
• error_reporting(E_ALL) 开启时,未定义变量警告也会提前触发输出
• session_start() 前调用了 header() → session cookie头会冲突
• 使用 echo 或 print 后再调用 header() → 直接报“headers already sent”
验证方法:在调用 header() 前加一句 if (headers_sent($file, $line)) { die("Headers sent in $file on line $line"); }
Content-Type和Content-Disposition组合怎么选
下载行为由两个头共同决定,缺一不可:
• Content-Type 决定浏览器如何解析数据流,不是文件扩展名的简单映射
– 二进制文件(PDF/ZIP/XLSX)统一用 application/octet-stream 最稳妥
– 已知类型可更精确:Excel用 application/vnd.openxmlformats-officedocument.spreadsheetml.sheet,CSV用 text/csv
• Content-Disposition 决定是否弹下载框及默认文件名
– attachment; filename="xxx.xlsx" → 强制下载,文件名固定
– inline; filename="xxx.pdf" → 尝试在浏览器内打开(PDF常支持,图片也行)
– filename* 参数(RFC 5987)用于UTF-8中文名,但IE不支持,建议用 urlencode() 兼容处理
特别注意:Content-Type: application/force-download 是非标准伪类型,部分旧浏览器识别,现代浏览器忽略;不要依赖它。



















