Laravel ファイルアップロード時にバリデーションで「The file failed to upload.」と表示される

## 〜宣伝〜

:::note info
個人開発でエンジニア専門マッチングサービスを開発しましたので、是非未経験からエンジニア目指している人！現役エンジニアで教えたい人！使ってみてください！

β版リリース記念キャンペーン中です！

10名様限定、抽選でお好きな技術本1冊プレゼント！
🎉当選者にはメッセージ差し上げます(送付の際に住所はお聞きしません)
詳しくはこちらから↓

https://x.com/dokupro01/status/1796837336145436846
:::
https://dokupro.dev/

# 目的

- ファイルアップロード時にバリデーションエラーで「The file failed to upload.」と出力される問題を解決する。

# 環境

- ハードウェア環境

| 項目 | 情報 |
| --- | --- |
| OS | macOS Catalina(10.15.5) |
| ハードウェア | MacBook Pro (13-inch, 2020, Four Thunderbolt 3 ports) |
| プロセッサ | 2 GHz クアッドコアIntel Core i5 |
| メモリ | 32 GB 3733 MHz LPDDR4 |
| グラフィックス | Intel Iris Plus Graphics 1536 MB |

- ソフトウェア環境

| 項目 | 情報 | 備考 |
| --- | --- | --- |
| PHP バージョン | 7.4.11 | Homebrewを用いてこちらの方法で導入→[Mac HomebrewでPHPをインストールする](https://qiita.com/miriwo/items/cd54077aad7e139cf518) |
| Laravel バージョン | 6.X | commposerを用いてこちらの方法で導入→[Mac Laravelの環境構築を行う](https://qiita.com/miriwo/items/adaaaeecae69d6392e08) |
| MySQLバージョン | 8.0.21 for osx10.15 on x86_64 | Homwbrewを用いてこちらの方法で導入→[Mac HomebrewでMySQLをインストールする](https://qiita.com/miriwo/items/ef6a064bc545fbea29d9) |

# 問題までの経緯

1. laravelアプリでファイルをアップロードする機能を作成してファイルサイズ3 MB以下のバリデーションをかけた。
1. 7.4 MBの容量のファイルのアップロードを試みた。

# 問題

- バリデーションエラーに下記のメッセージが出力されてバリデーションで弾かれた。

    ```error
    The file failed to upload.
    ```

# 問題解決までの経緯

1. バリデーションのファイルサイズの記載を削除して再アップロードしても同じバリデーションエラーが発生する。
1. 流石にアップロードしたいファイルが大きすぎたと思いバリデーションをファイルサイズ1.6 MB以下に書き直した。

    ```php
    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'subject' => 'required',
            'content' => 'required',
            // 下記を修正
            'file' => 'file|max:1600|mimes:jpeg,png,jpg,pdf',
        ];
    }

    /**
     * バリデーションエラーメッセージ
     *
     * @return array
     */
    public function messages()
    {
        return [
            'subject.required' => 'メール件名を記入してください。',
            'content.required' => 'メール本文を記入してください。',
            'file.max' => '1.6MBを超えるファイルは添付できません。',
            'file.mimes' => '指定のファイル形式以外は添付できません。',
        ];
    }
    ```

1. 1.7 MBの画像ファイルをアップロードしてみたところ下記のバリデーションエラーが出力された。

    ```error
    1.6MBを超えるファイルは添付できません。
    ```

1. これは自分で設定したバリデーションルールによって弾かれていることを表す。
1. php.iniファイルにアップロードできるファイルサイズの上限を指定している部分があるようなので見てみる。
1. 下記方法を使ってphp.iniファイルの場所を突き止めて開いてみた。
    - [php.iniファイルの場所をターミナルで確認する](https://qiita.com/miriwo/items/acb49b0a97b5d5fa47fd)
1. 下記の2つの項目をviの検索機能を用いて検索した。
    - `post_max_size`: PHPが受け入れる投稿データの最大サイズ
    - `upload_max_filesize`: アップロードされたファイルの最大許容サイズ
1. 下記のように`post_max_size`は8 MB、`upload_max_filesize`は2 MBと指定されていた。

    ![MailRequest_php_—_laravel6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/06ef402b-b024-c19c-b365-ff0bd59dbf21.png)
    ![MailRequest_php_—_laravel6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/55b60b0d-51d3-13ec-aaba-73c02e0a049f.png)

1. どうやらセキュリティ上の理由からアップロードファイルのサイズに制限がかかっているようだ。
1. 7.4 MBのファイルをアップロードする際に弾かれたので`upload_max_filesize`に弾かれたと思われる。
1. sudoコマンドを駆使しviでphp.iniを開き`post_max_size`と`upload_max_filesize`をそれぞれ「10M」に修正した。
1. laravelのバリデーションの記載を下記のように修正した。

    ```php
    /**
     * Get the validation rules that apply to the request.
     *
     * @return array
     */
    public function rules()
    {
        return [
            'subject' => 'required',
            'content' => 'required',
            // 下記を修正
            'file' => 'file|max:10000|mimes:jpeg,png,jpg,pdf',
        ];
    }

    /**
     * バリデーションエラーメッセージ
     *
     * @return array
     */
    public function messages()
    {
        return [
            'subject.required' => 'メール件名を記入してください。',
            'content.required' => 'メール本文を記入してください。',
            'file.max' => '10 MBを超えるファイルは添付できません。',
            'file.mimes' => '指定のファイル形式以外は添付できません。',
        ];
    }
    ```

1. 7.4 MBの容量のファイルのアップロードを試みたところバリデーションに弾かれることなくファイルアップロードをすることができた。

# 参考文献

- [https://www.php.net/manual/ja/ini.core.php#ini.post-max-size](https://www.php.net/manual/ja/ini.core.php#ini.post-max-size)
- [https://www.php.net/manual/ja/ini.core.php#ini.upload-max-filesize](https://www.php.net/manual/ja/ini.core.php#ini.upload-max-filesize)