0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

PHP、Laravelのアップロード処理整理

0
Last updated at Posted at 2025-11-20

概要

アップロード処理実装中、php.iniの upload_max_filesize の値が小さくエラー発生。
原因特定に時間を要したので処理フローを整理しておく。

PHPの処理

参考: POST メソッドによるアップロード

  1. form から受信したファイルを一時的な場所に保管 (デフォルト=>サーバーのデフォルト一時ディレクトリ。 upload_tmp_dir が定義されていた場合はそこ。)
  2. アップロードされたファイルに関する情報がグローバル変数である $_FILES 連想配列に格納される

$_FILESの内容

※userfileはアプロードファイルの仮名。任意の名称を使用可能。

$_FILES['userfile']['name'] クライアントマシンの元のファイル名。
$_FILES['userfile']['type'] ファイルの MIME 型。
$_FILES['userfile']['size'] アップロードされたファイルのバイト単位のサイズ。
$_FILES['userfile']['tmp_name'] アップロードされたファイルがサーバー上で保存されているテンポラリファイルの名前。
$_FILES['userfile']['error'] このファイルアップロードに関する エラーコード
$_FILES['userfile']['full_path'] ブラウザからアップロードされたファイルのフルパス。(PHP 8.1.0 以降で利用可能)

Laravelの処理

  1. PHPのグローバル変数から、Illuminate/Http/Request を生成する
    public/index.php
    $kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);
    
    $response = $kernel->handle(
        $request = Illuminate\Http\Request::capture()
    );
    
    $response->send();
    
    $kernel->terminate($request, $response);
    
    vendor/laravel/framework/src/Illuminate/Http/Request.php
    /**
     * Create a new Illuminate HTTP request from server variables.
     *
     * @return static
     */
    public static function capture()
    {
        static::enableHttpMethodParameterOverride();
    
        return static::createFromBase(SymfonyRequest::createFromGlobals());
    }
    
    ※ここでグローバル変数から値を取得して変換している( $_FILES も)
    vendor/symfony/http-foundation/Request.php
    /**
     * Creates a new request with values from PHP's super globals.
     */
    public static function createFromGlobals(): static
    {
        $request = self::createRequestFromFactory($_GET, $_POST, [], $_COOKIE, $_FILES, $_SERVER);
    
        if (str_starts_with($request->headers->get('CONTENT_TYPE', ''), 'application/x-www-form-urlencoded')
            && \in_array(strtoupper($request->server->get('REQUEST_METHOD', 'GET')), ['PUT', 'DELETE', 'PATCH'], true)
        ) {
            parse_str($request->getContent(), $data);
            $request->request = new InputBag($data);
        }
    
        return $request;
    }
    
  2. $_FILESの中身が Symfony\Component\HttpFoundation\FileBag に変換される
    vendor/symfony/http-foundation/Request.php
        public function initialize(array $query = [], array $request = [], array $attributes = [], array $cookies = [], array $files = [], array $server = [], $content = null): void
    {
        $this->request = new InputBag($request);
        $this->query = new InputBag($query);
        $this->attributes = new ParameterBag($attributes);
        $this->cookies = new InputBag($cookies);
        $this->files = new FileBag($files);
        $this->server = new ServerBag($server);
        $this->headers = new HeaderBag($this->server->getHeaders());
        //省略
    
  3. 各ファイルが Symfony\Component\HttpFoundation\File\UploadedFileに変換される。なお、$request->file('key') などで呼び出す際に Illuminate\Http\UploadedFile に変換される

上記がアップロードファイルのフローである。

UploadedFileの内容サンプル

成功時

Illuminate\Http\UploadedFile {#538 // app/Http/Controllers/SomeController.php:40
  -originalName: "xxx.csv"
  -mimeType: "text/csv"
  -error: 0
  -originalPath: "xxx.csv"
  -test: false
  #hashName: null
  path: "/tmp"
  filename: "phpYtI8ep"
  basename: "phpYtI8ep"
  pathname: "/tmp/phpYtI8ep"
  extension: ""
  realPath: "/tmp/phpYtI8ep"
  aTime: 2025-11-20 15:54:54
  mTime: 2025-11-20 15:54:54
  cTime: 2025-11-20 15:54:54
  inode: 728
  size: 5385
  perms: 0100600
  owner: 33
  group: 33
  type: "file"
  writable: true
  readable: true
  executable: false
  file: true
  dir: false
  link: false
}

失敗時

例: ファイルサイズ超過の場合

  • errorに0以上の値が入っている(一覧は後述)
  • 情報がスカスカ
Illuminate\Http\UploadedFile {#40 // app/Http/Controllers/SomeController.php:xx
  -originalName: "xxx.csv"
  -mimeType: "application/octet-stream"
  -error: 1
  -originalPath: "xxx.csv"
  -test: false
  path: ""
  filename: ""
  basename: ""
  pathname: ""
  extension: ""
  realPath: "/var/www/public"
  aTime: 1970-01-01 09:00:00
  mTime: 1970-01-01 09:00:00
  cTime: 1970-01-01 09:00:00
  inode: false
  size: false
  perms: 00
  owner: false
  group: false
  type: false
  writable: false
  readable: false
  executable: false
  file: false
  dir: false
  link: false
}

エラーコードの種類

引用: エラーメッセージの説明

$phpFileUploadErrors = array(
0 => 'There is no error, the file uploaded with success',
1 => 'The uploaded file exceeds the upload_max_filesize directive in php.ini',
2 => 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form',
3 => 'The uploaded file was only partially uploaded',
4 => 'No file was uploaded',
6 => 'Missing a temporary folder',
7 => 'Failed to write file to disk.',
8 => 'A PHP extension stopped the file upload.',
);

アップロードに関連する php.ini の設定項目

  • upload_max_filesize: 単一ファイルのサイズ上限
  • post_max_size: POSTで送信されるデータ全体の最大サイズ。upload_max_filesize より大きい必要あり
  • memory_limit: PHPが使用できるメモリの最大値。デカいファイルはメモリも消費するため
  • max_execution_time: 実行できる最大の秒数。デカいファイルは処理時間もかかりがちなため
  • max_file_uploads: 一度にアップロードできるファイル数の上限

エラー時の調査方法

アップロードファイルのファイルサイズ超過等のエラーは、例外を発生させない。
詳細は、UploadFileのエラーコードを確認するのが良い。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?