跳到内容

413 Request Entity Too Large错误:原因和解决方法 | Nginx、PHP、Apache完全支持

分类:服务器·HTTP
本文目前仅提供日文版本。我们正在进行翻译工作。

在实现文件上传功能时,可能会在浏览器中突然看到「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>