系统实践
Nginx 反向代理上传失败:从 HTTP 错误到完整排查
上传失败不一定是应用程序的问题。从一次真实故障出发,整理请求体大小、临时目录、超时与上游限制的排查顺序。

本文最初发布于 2017 年。2026 年修订时保留了真实排查过程,并根据当前 Nginx 官方文档重新核验配置。
问题不一定在 WordPress
当时的现象是 WordPress 上传附件时提示 HTTP 错误。我围绕“WordPress 上传 HTTP 错误”搜索了一整晚,却始终没有找到答案。
第二天换了一个角度:同一台服务器上的其他网站能不能上传?测试后发现,另一个 WordPress 和一个 Drupal 网站也会失败,只是分别显示 HTTP 错误和 500 错误。
这一步把问题范围从“某个 WordPress”扩大到了“整条上传链路”。继续检查后,最终定位到 Nginx 反向代理层。
当一个局部问题久查不出时,先找对照组,确认故障属于应用、代理、网络还是存储层。
先判断失败发生在哪一层
上传请求通常依次经过客户端、CDN 或 WAF、Nginx、上游应用以及文件存储。先做三个低成本检查:
sudo nginx -t
sudo tail -f /var/log/nginx/error.log
docker compose logs -f app
如果多个应用同时失败,优先检查公共代理层和磁盘;如果只有一个应用失败,再检查应用自身的上传限制和目录权限。
最常见的限制:client_max_body_size
client_max_body_size 限制客户端请求体大小。超过限制时,Nginx 会返回 413 Request Entity Too Large。
server {
server_name example.com;
client_max_body_size 100m;
location / {
proxy_pass http://app:8080;
}
}
不要为了省事设置成无限大。上传上限应略高于业务允许值,同时核对 CDN、应用框架、PHP 和对象存储的限制。修改后先检查再重载:
sudo nginx -t
sudo nginx -s reload
临时目录与磁盘权限
旧故障还涉及请求体临时目录。请求体大于内存缓冲区时,Nginx 可能把数据写入 client_body_temp_path。目录不存在、Nginx 用户无写权限、磁盘已满或 inode 耗尽,都可能表现为上传失败。
df -h
df -i
sudo ls -ld /var/lib/nginx/body
只有确实需要自定义路径时才配置:
http {
client_body_temp_path /var/lib/nginx/body 1 2;
}
旧文把临时目录放在 /etc/nginx,新版不再推荐这种做法:配置目录不适合作为运行时写入位置。
请求缓冲不是响应缓冲
proxy_request_buffering控制客户端上传的请求体是否先由 Nginx 完整读取;proxy_buffering控制 Nginx 如何读取上游返回的响应。
大文件需要边接收边转发时,可以只对上传路径关闭请求缓冲:
location /api/upload/ {
client_max_body_size 100m;
proxy_http_version 1.1;
proxy_request_buffering off;
proxy_pass http://app:8080;
}
关闭请求缓冲后,请求一旦开始发往上游,通常无法再安全重试到另一台服务器,因此不要把它当作所有上传错误的通用开关。
再检查超时与上游限制
location /api/upload/ {
client_max_body_size 100m;
proxy_connect_timeout 10s;
proxy_send_timeout 120s;
proxy_read_timeout 120s;
proxy_pass http://app:8080;
}
超时不宜盲目设成几小时。应根据文件大小、最低可接受带宽和上游处理时间估算,再通过日志确认是客户端发送慢、代理写入慢,还是上游处理慢。
即使 Nginx 接受请求,上游仍可能拒绝。PHP 的 upload_max_filesize 与 post_max_size、应用框架的 body limit、对象存储的单次上传限制,都必须一起核对。
可复用的排查顺序
- 记录状态码、失败文件大小和时间;
- 用小文件和大文件做对照;
- 同时检查 Nginx 与上游日志;
- 核对整条链路的上传大小限制;
- 检查临时目录权限、磁盘和 inode;
- 再判断是否需要调整请求缓冲与超时;
- 使用
nginx -t验证,灰度测试后再上线。
旧文章只给出了最终三行配置。那能解决当时的问题,却不适合作为通用答案。真正可长期复用的,是先缩小故障层级,再用日志和对照实验验证假设。
