附件下载404通常因nginx未正确配置静态文件路由,导致请求未进php;应确认文件放public目录、添加精准location规则匹配后缀并设root指向public,避免fallback至index.php。

附件下载地址返回404,通常不是 Symfony 2 路由没配好,而是请求根本没进 PHP,被 Nginx(或 Apache)提前拦截了——静态文件路径不匹配、location 规则冲突、或文件物理位置不对。
确认请求是否进入 Symfony
先看浏览器开发者工具的 Network 标签页,点开那个 404 请求,看Response Headers里有没有 X-Powered-By: PHP 或 X-Symfony-Debug: 1。没有?说明请求压根没到 index.php,是 Web 服务器直接返回的 404。
- 如果响应头里有
Server: nginx但没 PHP 相关字段,基本可断定是 Nginx 静态路由配置问题 - 如果是 Apache,检查
.htaccess是否在public/目录下且启用AllowOverride All - 用
curl -I http://yoursite.com/path/to/file.pdf看原始状态码和 headers,排除浏览器缓存干扰
检查 Nginx 的静态文件 location 规则
Symfony 的 public 目录是 Web 根目录,所有附件应放在 public/ 下(比如 public/uploads/report.pdf),且 Nginx 必须明确允许访问这类路径,不能全部 fallback 到 index.php。
- 确保有类似这样的 location 块(放在 server 配置内,优先级高于通用 / 匹配):
location ~* \.(pdf|doc|xls|zip|png|jpg|gif)$ {
root /var/www/your-app/public;
try_files $uri =404;
}-
root必须指向public/目录,不是项目根目录 -
try_files $uri =404表示:如果文件存在就直接返回;不存在才返回 404(而不是交给 PHP) - 避免写成
try_files $uri /index.php$is_args$args—— 这会让 PDF 请求也走 PHP,而 Symfony 默认不处理静态文件路由
验证文件路径与 URL 是否一致
Symfony 2 不提供“附件路由生成器”,下载链接必须是真实可访问的 HTTP 路径,不是控制器路径。
- 错误写法:
/app_dev.php/download?id=123(这是动态接口,需自己实现逻辑) - 正确做法:把文件放
public/uploads/xxx.pdf,链接直接写/uploads/xxx.pdf - 检查 Linux 文件权限:
ls -l public/uploads/xxx.pdf,确保 web 用户(如 www-data)有读取权限 - 路径区分大小写,
/Uploads/和/uploads/是两个不同目录
若坚持用控制器返回文件(非直接 URL)
那就得手动构造 Response,并确保路由能匹配、文件路径可读。
- 路由定义要明确,比如:
download_file: path: /download/{filename} - 控制器里用
file_get_contents($absolutePath)前,务必is_readable($absolutePath)校验 - 别用相对路径:
../uploads/xxx.pdf,应从__DIR__.'/../../public/uploads/xxx.pdf'构建绝对路径 - 返回 Response 时设好 header:
Content-Type: application/pdf、Content-Disposition: attachment; filename="xxx.pdf"











