17.

Laravel PostTooLargeException の原因と対処完全ガイド

編集
この記事の要点
  • PostTooLargeException = php.inipost_max_size を POST データが超過したときに発生
  • 対処1: upload_max_filesize / post_max_size / memory_limitphp.ini で増やす
  • 対処2: Nginx の client_max_body_size、Apache の LimitRequestBody も合わせて引き上げ
  • 対処3: php-fpm がプロセス分離なら /etc/php/8.3/fpm/php.ini を編集 + systemctl restart php8.3-fpm
  • 根本対策: 画像はフロントで圧縮、巨大ファイルはチャンク分割 / 直 S3 アップロード

エラーの全体像

Illuminate\Http\Exceptions\PostTooLargeException

The POST data is too large.

at vendor/laravel/framework/src/Illuminate/Foundation/Http/Middleware/ValidatePostSize.php

HTTP Status: 413 Payload Too Large

Laravel の ValidatePostSize ミドルウェアがリクエストサイズと post_max_size を比較し、超えていれば即座にこの例外を投げます。$_POST$_FILES が空になるのを未然に検知する仕組みです。

原因の切り分け

確認方法該当時の対処
php.ini の値php -i | grep post_max_size対処1
php-fpm 用の ini を編集したかphp --ini でロードされる ini を確認対処1(FPM 用)
Nginx の上限nginx -T | grep client_max_body_size対処2
Apache の上限httpd -M | grep limit対処2
サービス再起動したかsystemctl status php8.3-fpm再起動

対処1: php.ini を編集

; /etc/php/8.3/fpm/php.ini (Laravel の本番では FPM 用)
; /etc/php/8.3/cli/php.ini (CLI 用、artisan 用)

; 1 ファイルあたり最大サイズ
upload_max_filesize = 50M

; POST 全体のサイズ上限(複数ファイル+他フィールド合計)
; ★ upload_max_filesize より大きく設定
post_max_size = 60M

; メモリ上限(画像処理する場合大きめに)
memory_limit = 512M

; 同時に送れるファイル数
max_file_uploads = 20

; アップロード時間
max_execution_time = 300
max_input_time = 300

編集後の反映:

# php-fpm を再起動
sudo systemctl restart php8.3-fpm

# Apache の mod_php なら Apache を再起動
sudo systemctl restart apache2

# 反映確認
php -i | grep -E "post_max_size|upload_max_filesize"
# 本番 FPM 経由なら phpinfo() を吐く一時 PHP を作って確認:
# <?php phpinfo();

対処2: Nginx の client_max_body_size

Nginx はPHP より先にリクエストサイズを判定して 413 を返します。php.ini だけ上げても Nginx で弾かれるので両方必須:

# /etc/nginx/nginx.conf (http コンテキスト)
http {
    client_max_body_size 60M;
}

# または特定 server / location だけ
server {
    listen 80;
    server_name example.com;

    client_max_body_size 60M;     # ← サーバ全体

    location /api/upload {
        client_max_body_size 200M;  # ← このパスだけ大きめ
    }
}
# 構文チェック → 反映
sudo nginx -t
sudo systemctl reload nginx

対処3: Apache の LimitRequestBody

# .htaccess または httpd.conf
LimitRequestBody 62914560     # 60MB (バイト単位)

# 特定パスだけ大きく
<Directory "/var/www/html/upload">
    LimitRequestBody 209715200    # 200MB
</Directory>

# mod_php の場合、ini 値も .htaccess で上書き可
php_value upload_max_filesize 50M
php_value post_max_size 60M
php_value memory_limit 512M

対処4: Laravel ミドルウェアでより親切なメッセージ

標準では 413 + 例外画面ですが、ハンドラでカスタマイズできます:

// app/Exceptions/Handler.php (Laravel 10 以前)
use Illuminate\Http\Exceptions\PostTooLargeException;

public function register(): void
{
    $this->renderable(function (PostTooLargeException $e, $request) {
        if ($request->expectsJson()) {
            return response()->json([
                'message' => 'アップロードサイズが大きすぎます (上限 60MB)',
                'code'    => 'POST_TOO_LARGE',
            ], 413);
        }
        return response()->view('errors.413', [], 413);
    });
}

// Laravel 11+ bootstrap/app.php
->withExceptions(function ($exceptions) {
    $exceptions->render(function (PostTooLargeException $e, $request) {
        if ($request->expectsJson()) {
            return response()->json([
                'message' => 'アップロードサイズが大きすぎます',
            ], 413);
        }
        return response()->view('errors.413', [], 413);
    });
})

サイズ単位の注意

場所単位
php.iniK / M / Gpost_max_size = 60M
Nginxk / m / gclient_max_body_size 60m;
Apacheバイト数(数字のみ)LimitRequestBody 62914560

php-fpm の編集箇所

Laravel 本番では通常 php-fpm 経由で動きます。CLI 用 php.ini を編集しても Web 経由のアップロードには反映されません:

# CLI 用 ini の場所
php --ini
# Configuration File (php.ini) Path: /etc/php/8.3/cli
# Loaded Configuration File:         /etc/php/8.3/cli/php.ini

# FPM 用は別ディレクトリ
ls /etc/php/8.3/fpm/php.ini

# FPM プール(プロセスごとの設定)も影響
ls /etc/php/8.3/fpm/pool.d/www.conf

# プールごとに ini 値を上書き可能
# /etc/php/8.3/fpm/pool.d/www.conf
# php_admin_value[post_max_size] = 100M
# php_admin_value[upload_max_filesize] = 100M

根本対策: 巨大ファイル UP の設計

方針説明
画像のフロント圧縮browser-image-compression / Canvas で送信前にリサイズ・圧縮
チャンクアップロードtus-js-client / resumable.js で分割送信、サーバで結合
S3 直 PUT署名付き URL を発行し、ブラウザ→S3 直接送信(API サーバを経由しない)
マルチパート S3AWS SDK の Multipart Upload で 100MB 以上を効率送信
動画は HLS / DASH 配信事前にトランスコードし、HTTP で部分配信

S3 署名付き URL の例

use Aws\S3\S3Client;

$s3 = new S3Client(['version' => 'latest', 'region' => 'ap-northeast-1']);

$cmd = $s3->getCommand('PutObject', [
    'Bucket' => 'my-bucket',
    'Key'    => 'uploads/' . uniqid() . '.jpg',
    'ContentType' => 'image/jpeg',
]);

$presigned = (string) $s3->createPresignedRequest($cmd, '+15 minutes')->getUri();
// → このURLを返し、ブラウザから PUT すれば S3 直アップロード
//   Laravel サーバを経由しないので PostTooLargeException 自体起きない

FAQ

Q: php.ini を変更したのに反映されない
A: php-fpm の再起動を忘れているケースが大半。sudo systemctl restart php8.3-fpm 必須。CLI ではなく FPM 用 ini を編集しているかも確認。

Q: 413 が出るが Laravel のスタックトレースが出ない
A: Nginx が 413 を返している(PHP まで届いていない)。Nginx の client_max_body_size を確認。

Q: アップロード途中で接続が切れる
A: Nginx の client_body_timeout / Cloudflare の 100MB 上限 / php-fpm の request_terminate_timeout を確認。

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. SQLSTATE[HY000] [1045] Access denied for user 'homestead'@'localhost'
  2. Add [~] to fillable property to allow mass assignment on [App\~].
  3. PHP Parse error: syntax error, unexpected 'class' (T_CLASS), expecting identifier (T_STRING) or variable (T_VARIABLE) or '{' or '$' in ~
  4. Changing columns for table "~" requires Doctrine DBAL; install "doctrine/dbal"
  5. MethodNotAllowedHttpException No message
  6. Class 'Doctrine\DBAL\Driver\PDOMySql\Driver' not found
  7. production.ERROR: No application encryption key has been specified.
  8. Dotenv values containing spaces must be surrounded by quotes.
  9. Laravel \ Socialite \ Two \ InvalidStateException
  10. The page has expired due to inactivity. Please refresh and try again.
  11. Failed to clone https://github.com/symfony/thanks.git via https, ssh protocol
  12. Illegal offset type
  13. Cannot access protected property Illuminate\Http\Request::$...
  14. Emitted value instead of an instance of Error
  15. 画像保存時にInternal Server Error
  16. Failed to authenticate on SMTP server with username ...
  17. PostTooLargeException
  18. Database hosts array is empty.
  19. Invalid request (Unsupported SSL request)
  20. does not comply with psr-4 autoloading standard. Skipping.
  21. MySQLのSTR_TO_DATE関数を使用するとnullが返却される問題

最近更新/作成されたページ