如何正确配置Nginx的client_max_body_size | 上传限制问题排查
在 Nginx 中实现文件上传时,「小文件可以上传,但上传大文件时出现 413 错误」的问题非常常见。原因几乎总是 <code>client_max_body_size</code> 配置不足。然而,仅修复 Nginx 配置通常无法解决问题,需要全面理解 PHP 的 <code>upload_max_filesize</code> 和 <code>post_max_size</code>,以及超时设置。本文系统地解释了与上传限制相关的所有配置项。
client_max_body_size的默认值和作用
Nginx有一个<code>client_max_body_size</code>指令,用于限制来自客户端的请求体的最大大小。默认值为<code>1m</code>(1 MiB)。超过此限制的请求会立即被拒绝,返回<code>413 Request Entity Too Large</code>错误。
由于默认值仅为 1m,即使上传单张图片或 PDF 也会很快达到限制。在实际生产环境中,需要根据用途适当提高这个值。
配置位置:http / server / location 的差异
<code>client_max_body_size</code> 可以在 Nginx 的任何配置级别(http / server / location)设置。更具体的范围设置优先。
# http ブロック(全サーバー共通)
http {
client_max_body_size 10m;
server {
listen 80;
server_name example.com;
# server ブロック(このバーチャルホスト全体)
client_max_body_size 50m;
location /upload {
# location ブロック(このパスのみ)
# より大きなファイルを許可したい場合
client_max_body_size 200m;
proxy_pass http://app;
}
location /api {
# APIエンドポイントはデフォルト(1m)のままにする例
client_max_body_size 1m;
}
}
}
仅为上传专用端点设置较大值,而保持其他端点较小是安全最佳实践。可以指定 <code>0</code> 以实现无限制,但这会增加 DoS 攻击风险,不推荐。
413 Request Entity Too Large错误的原因和解决方案
我们将整理413错误的原因和处理方法。
| 原因 | 检查项 | 解决方案 |
|---|---|---|
| Nginx 限制超出 | nginx.conf 中的 <code>client_max_body_size</code> | 提高值 |
| PHP限制超出 | php.ini 中的 <code>upload_max_filesize</code> | 提高值 |
| 整个 POST 正文超过限制 | php.ini 中的 <code>post_max_size</code> | 设置为大于 upload_max_filesize |
| 反向代理限制 | 上游 Nginx 或负载均衡器配置 | 检查每个阶段的代理 |
修改 Nginx 配置后,必须重新加载。
# 設定の文法チェック
nginx -t
# 設定のリロード(サービス停止なし)
nginx -s reload
# または systemd 経由
systemctl reload nginx
与PHP的upload_max_filesize / post_max_size的关系
仅提高 Nginx 的 <code>client_max_body_size</code> 是不够的。如果后端是 PHP,PHP 级别也有独立的限制。只有当这 3 个设置都设置为适当的值时,上传才会成功。
; php.ini の設定
; 1ファイルあたりの上限
upload_max_filesize = 100M
; POSTリクエスト全体の上限(upload_max_filesize より大きくする)
; multipart/form-data のオーバーヘッド分を見込んで多めに設定
post_max_size = 110M
; メモリ上限(post_max_size より大きくする)
memory_limit = 256M
; アップロード処理の実行時間(大容量ファイル用に延ばす)
max_execution_time = 300
max_input_time = 300
重要配置值之间的关系如下。
- client_max_body_size(Nginx) ≥ post_max_size(PHP) ≥ upload_max_filesize(PHP)
- 如果 Nginx 拒绝请求,处理永远无法到达 PHP
- <code>post_max_size</code> 是整个 POST 请求体的大小限制,包括多个文件上传和非文件表单字段
proxy_read_timeout / proxy_send_timeout 的重要性
上传大文件时,超时设置也很重要。默认的 <code>proxy_read_timeout</code> 为 60 秒,如果上传耗时过长,处理将被中断。
location /upload {
client_max_body_size 500m;
proxy_pass http://app_backend;
# バックエンドからのレスポンス待機時間
# 大容量ファイルの処理には長めに設定
proxy_read_timeout 600s;
# クライアントへのデータ送信待機時間
proxy_send_timeout 600s;
# バックエンドへの接続タイムアウト
proxy_connect_timeout 60s;
# クライアントのリクエストボディ受信タイムアウト
# 2回の連続した読み取り操作の間の時間
client_body_timeout 120s;
}
建议为上传端点和常规 API 端点设置不同的超时值。
Docker 中的配置(nginx.conf 挂载)
在 Docker 环境中,自定义 nginx.conf 或 conf.d 文件被挂载到容器中以应用配置。
# Dockerfile でのカスタム設定追加
FROM nginx:alpine
# カスタム設定ファイルをコピー
COPY ./nginx/conf.d/upload.conf /etc/nginx/conf.d/upload.conf
# デフォルト設定を完全に置き換える場合
# COPY ./nginx/nginx.conf /etc/nginx/nginx.conf
# docker-compose.yml でのボリュームマウント
version: '3.8'
services:
nginx:
image: nginx:alpine
volumes:
# ディレクトリごとマウント(変更が即反映される)
- ./nginx/conf.d:/etc/nginx/conf.d
# または特定ファイルだけマウント
# - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
ports:
- "80:80"
# nginx/conf.d/upload.conf
server {
listen 80;
server_name localhost;
# グローバルのアップロード上限
client_max_body_size 100m;
location / {
proxy_pass http://app:9000;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
}
location /upload {
client_max_body_size 500m;
proxy_pass http://app:9000;
proxy_read_timeout 600s;
proxy_send_timeout 600s;
}
}
配置确认命令
要检查当前Nginx配置中<code>client_max_body_size</code>的值,使用<code>nginx -T</code>展开所有设置后再进行grep搜索会很方便。
# 全設定を展開して client_max_body_size を検索
nginx -T | grep -i body_size
# 出力例:
# client_max_body_size 1m; ← デフォルト(http ブロック)
# client_max_body_size 100m; ← カスタム設定(server ブロック)
# 設定ファイルのパスも確認
nginx -T | grep "# configuration"
# 特定の設定ファイルだけチェック
nginx -t -c /etc/nginx/nginx.conf
# 現在読み込まれている設定のダンプ
nginx -T 2>/dev/null | grep -A1 "client_max"
常见配置错误及解决方法
- <strong>单位错误</strong>:<code>client_max_body_size 100</code> 默认为字节。必须指定单位,例如 <code>100m</code>
- <strong>层级疏漏</strong>:你以为在 location 块中覆盖,但上层的 server 块或 http 块正在生效
- <strong>忘记重新加载</strong>:修改配置文件后,如果不运行 <code>nginx -s reload</code>,更改将不会生效
- <strong>多个 server 块</strong>:通过 include 加载的其他 conf.d 文件产生冲突
- <strong>与 PHP 的不匹配</strong>:即使提高 Nginx 限制,如果 PHP 的 <code>upload_max_filesize</code> 仍然较低,可能会出现 413 之外的错误
本文中可用的测试文件(免费)
- → <a href="/ja/files/threshold/" class="text-primary-600 dark:text-primary-400 hover:underline">边界值测试文件列表</a> — 通过 client_max_body_size 配置值前后的文件重现错误
- → <a href="/ja/files/images/png/" class="text-primary-600 dark:text-primary-400 hover:underline">PNG 测试图像列表</a> — 使用各种大小的 PNG 图像验证 Nginx 限制
相关文章
- → <a href="/ja/blog/how-to-test-upload-limit/" class="text-primary-600 dark:text-primary-400 hover:underline">如何正确测试文件上传限制</a>
- → <a href="/ja/blog/multipart-form-data-overhead/" class="text-primary-600 dark:text-primary-400 hover:underline">准确计算 multipart/form-data 的开销</a>
- → <a href="/ja/blog/mb-vs-mib-file-size/" class="text-primary-600 dark:text-primary-400 hover:underline">MB 和 MiB 的区别|文件大小单位的正确理解</a>