413 Request Entity Too Large错误:原因和解决方法 | Nginx、PHP、Apache完全支持
在实现文件上传功能时,可能会在浏览器中突然看到「413 Request Entity Too Large」错误。当发送的请求正文大小超过服务器配置的限制时,会返回这个 HTTP 状态代码。本文全面涵盖了 Nginx、PHP 和 Apache 的配置位置,系统地解释了如何识别原因并解决问题。
什么是 413 错误
HTTP 413 状态码(在 RFC 9110 中改名为 "Content Too Large")在客户端发送的请求体超过服务器最大处理大小时返回。这不仅发生在文件上传,也发生在大型 JSON 负载或 Base64 编码数据传输中。
当发生此错误时,服务器拒绝请求本身,因此在处理到达应用程序代码(PHP、Python等)之前连接就会关闭。因此,应用程序日志中不会留下记录,需要检查Web服务器的错误日志。
Nginx: client_max_body_size 配置
默认情况下,Nginx 的 <code>client_max_body_size</code> 设置为 <strong>1MB</strong>。对于接受图像或 PDF 上传的网站,几乎肯定需要提高这个值。
# /etc/nginx/nginx.conf(グローバル設定)
http {
# すべての仮想ホストに適用
client_max_body_size 100m;
server {
listen 80;
server_name example.com;
# このサーバーブロック内のみに適用(httpの値を上書き)
client_max_body_size 50m;
location /api/upload {
# このlocationのみに適用(serverの値を上書き)
client_max_body_size 200m;
proxy_pass http://backend;
}
}
}
设置的优先级顺序为 <code>location</code> > <code>server</code> > <code>http</code>。如果您只想增加特定上传端点的限制,在 <code>location</code> 块中指定是最佳实践。
# 設定変更後はNginxをリロード
sudo nginx -t # 構文チェック
sudo systemctl reload nginx # リロード(ダウンタイムなし)
# エラーログの確認
tail -f /var/log/nginx/error.log
# 413エラー時のログ例:
# client intended to send too large body: 10485760 bytes
PHP: upload_max_filesize / post_max_size / memory_limit 的关系
PHP有多个大小限制,需要正确理解它们之间的关系。始终配置以满足以下不等式。
; php.ini の設定
; 必ず以下の関係を維持すること:
; upload_max_filesize <= post_max_size <= memory_limit
; 1ファイルあたりの最大サイズ
upload_max_filesize = 50M
; POSTリクエスト全体の最大サイズ(複数ファイルの合計 + フォームデータ)
post_max_size = 100M
; PHPスクリプトが使用できる最大メモリ
memory_limit = 256M
; ファイルアップロードの最大数
max_file_uploads = 20
; アップロードの一時保存先
upload_tmp_dir = /tmp
| 指令 | 默认值 | 影响范围 |
|---|---|---|
upload_max_filesize |
2M | 单个文件的最大大小 |
post_max_size |
8M | 整个 POST 请求(文件 + 表单数据) |
memory_limit |
128M | 脚本执行时的最大内存使用量 |
max_file_uploads |
20 | 可同时上传的文件数 |
max_execution_time |
30 | 脚本执行的最大秒数(大文件需要延长) |
max_input_time |
60 | 分析输入数据允许的最大秒数 |
// 現在のPHP設定値を確認するスクリプト
echo 'upload_max_filesize: ' . ini_get('upload_max_filesize') . PHP_EOL;
echo 'post_max_size: ' . ini_get('post_max_size') . PHP_EOL;
echo 'memory_limit: ' . ini_get('memory_limit') . PHP_EOL;
echo 'max_file_uploads: ' . ini_get('max_file_uploads') . PHP_EOL;
echo 'max_execution_time: ' . ini_get('max_execution_time') . PHP_EOL;
// php.ini の場所を確認
echo 'Loaded php.ini: ' . php_ini_loaded_file() . PHP_EOL;
Apache:LimitRequestBody 配置
在 Apache 中,使用 <code>LimitRequestBody</code> 指令来设置请求体的限制。默认值为 0(无限制),但建议出于安全考虑设置适当的限制。
# /etc/apache2/apache2.conf または .htaccess
# バイト単位で指定(100MB = 104857600 bytes)
# グローバル設定
LimitRequestBody 104857600
# 特定のディレクトリのみ
<Directory "/var/www/html/uploads">
LimitRequestBody 209715200
</Directory>
# 特定のURLパスのみ
<Location "/api/upload">
LimitRequestBody 209715200
</Location>
# .htaccess での設定(AllowOverride が必要)
# php_value upload_max_filesize 50M
# php_value post_max_size 100M
常见组合错误
413 错误的麻烦之处在于存在多个层级,每个层级都有各自的大小限制。即使修改了一个设置,请求也经常会在另一个层级被阻止。
情况1:通过Nginx但被PHP拒绝
如果 Nginx 的 <code>client_max_body_size</code> 设置为 100m,但 PHP 的 <code>upload_max_filesize</code> 仍为 2M,则 50MB 文件将通过 Nginx,但被 PHP 忽略。在这种情况下,HTTP 状态将返回 200,但文件将为空,<code>$_FILES</code> 将包含错误代码 1(UPLOAD_ERR_INI_SIZE)。
情况2:upload_max_filesize足够但post_max_size不足
即使设置 <code>upload_max_filesize = 50M</code>,如果 <code>post_max_size = 8M</code> 保持不变,任何超过 8MB 的请求都会被完全丢弃。在这种情况下,<code>$_POST</code> 和 <code>$_FILES</code> 都会成为空数组,这是一个令人困惑的行为。
情况3:反向代理配置中的疏漏
当使用 Nginx 作为反向代理,后端部署 Apache + PHP-FPM 时,需要在 Nginx、Apache 和 PHP 中都设置限制。
# Nginx リバースプロキシの設定
server {
client_max_body_size 100m;
location / {
proxy_pass http://127.0.0.1:8080;
# プロキシ関連のタイムアウトも延長(大容量ファイル対策)
proxy_read_timeout 300;
proxy_connect_timeout 300;
proxy_send_timeout 300;
# バッファリングの設定
proxy_request_buffering on;
proxy_buffering on;
proxy_buffer_size 128k;
proxy_buffers 4 256k;
}
}
调试步骤
当发生413错误时,请按照以下步骤确定原因。
# 1. どのレイヤーでブロックされているか確認
# Nginx のエラーログを確認
tail -n 50 /var/log/nginx/error.log | grep "too large"
# 2. PHP の設定値を確認
php -i | grep -E "upload_max|post_max|memory_limit"
# 3. PHP-FPM の設定ファイルを確認(php.ini とは別の場合がある)
php-fpm -i | grep -E "upload_max|post_max"
# または
find /etc -name "php.ini" -o -name "www.conf" | xargs grep -l "upload_max"
# 4. Apache の設定を確認
apachectl -t -D DUMP_RUN_CFG 2>/dev/null | grep -i limit
grep -r "LimitRequestBody" /etc/apache2/ /etc/httpd/
# 5. curl で実際にテスト(10MBのダミーファイルを送信)
dd if=/dev/zero of=/tmp/test_10mb.bin bs=1M count=10
curl -v -X POST -F "file=@/tmp/test_10mb.bin" https://example.com/api/upload
# 6. レスポンスヘッダーを確認
curl -I -X POST -F "file=@/tmp/test_10mb.bin" https://example.com/api/upload
测试方法
更改设置后,通过上传不同大小的文件进行测试非常重要。DevLab 提供了用于边界值测试的文件。在上限值前后进行测试(例如:如果上限是 50MB,则用 49MB、50MB、51MB 进行测试),并确认行为符合预期。
# JavaScript での送信テスト例
# 指定サイズのBlobを作成して送信する方法
# <script>
# async function testUpload(sizeMB) {
# const blob = new Blob(
# [new ArrayBuffer(sizeMB * 1024 * 1024)],
# { type: 'application/octet-stream' }
# );
# const formData = new FormData();
# formData.append('file', blob, 'test.bin');
#
# const response = await fetch('/api/upload', {
# method: 'POST',
# body: formData
# });
# console.log(sizeMB + 'MB:', response.status, response.statusText);
# }
#
# // 境界値テスト
# testUpload(1); // 1MB - 通常は成功
# testUpload(10); // 10MB - 設定による
# testUpload(50); // 50MB - 設定による
# testUpload(100); // 100MB - 通常は失敗
# </script>
各服务器推荐设置汇总
| 层 | 指令 | 推荐值(支持 50MB 上传) |
|---|---|---|
| Nginx | client_max_body_size |
60m(留有余量) |
| PHP | upload_max_filesize |
50M |
| PHP | post_max_size |
55M(大于 <code>upload_max_filesize</code>) |
| PHP | memory_limit |
256M |
| Apache | LimitRequestBody |
62914560(60MB,以字节为单位) |
本文中可用的测试文件(免费)
- → <a href="/ja/files/threshold/png/10mb/" class="text-primary-600 dark:text-primary-400 hover:underline">10MB 边界值测试 PNG</a> — 测试超过 Nginx 默认限制(1MB)
- → <a href="/ja/files/threshold/png/50mb/" class="text-primary-600 dark:text-primary-400 hover:underline">50MB 边界值测试 PNG</a> — 测试 upload_max_filesize 上限
- → <a href="/ja/files/threshold/" class="text-primary-600 dark:text-primary-400 hover:underline">边界值测试文件列表</a> — 各种大小的边界值测试文件
- → <a href="/ja/files/images/png/1mb/" class="text-primary-600 dark:text-primary-400 hover:underline">1MB 测试 PNG 图像</a> — 用于验证小尺寸的行为
相关文章
- → <a href="/ja/blog/nginx-upload-config/" class="text-primary-600 dark:text-primary-400 hover:underline">Nginx 文件上传配置指南 | client_max_body_size・proxy 设置</a>
- → <a href="/ja/blog/file-validation-checklist/" class="text-primary-600 dark:text-primary-400 hover:underline">Web 表单文件验证实现检查清单</a>
- → <a href="/ja/blog/http-422-error/" class="text-primary-600 dark:text-primary-400 hover:underline">422 Unprocessable Entity 错误:原因和解决方案</a>
- → <a href="/ja/blog/http-507-error/" class="text-primary-600 dark:text-primary-400 hover:underline">507 Insufficient Storage 错误:原因和解决方法</a>