【Laravel】CSVファイル・アップロードのバリデーションが通らなかった原因


画面からCSVアイルのアップロードをする機能を作ることになり、何の躓きも無いまま実装したので、ちょっくら実行してみるかと動作確認したところ、

バリデーションが通らない。。

軽くハマったので、解決までの流れを書いておきます。

環境

今回はあまり環境とかバージョンは関係ないけれど

  • Laravel5.4

最初に実装した内容(バリデーションが通らない)

画面側

input.blade.php
<form action="/upload/csv" method="post" >
    {{ csrf_field() }}

    <div class="form-group">
        {{ Form::label('csv_file', 'CSVファイル', ['class' => 'col-sm label-required']) }}
        <div class="col-sm">
            <label class="custom-file">
                <input type="file" accept=".csv" class="custom-file-input" name="csv_file" id="csv_file">
                <label class="custom-file-label custom-file-control" for="csv_file" data-browse="参照">ファイル選択...</label>
            </label>
            @component('form_error', ['errors' => $errors, 'field' => 'csv_file'])@endcomponent
        </div>
    </div>

    <div class="col-sm">
        <button type="form" class="btn btn-info">送信</button>
    </div>
</form>

フォームリクエスト

CsvUploadRequest.php
<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class CsvUploadRequest extends FormRequest
{
    public function authorize()
    {
        return true;
    }

    public function rules()
    {
        return [
            'csv_file' => 'required|file|mimes:csv',
        ];
    }

    public function messages()
    {
        return [
            'csv_file.file' => 'CSVファイルを選択してください'
        ];
    }

    public function attributes()
    {
        return [
            'csv_file' => 'CSVファイル',
        ];
    }
}

動かしてみる

CSVファイルを選択して、送信ボタンをポチっと。

何故だー。。

原因と修正

原因その1

最初のメッセージ見ると、fileルールで引っかかっている?そもそもアップロードできていない?

HTMLとかよくわかんないけど、記憶の片隅から「ファイルをアップロードする時って<form>タグの属性でなんか設定しなきゃいけなかったような気が」と思い出す。

・・・・・・。

enctype="multipart/form-data"だったかな?

ということで、修正しました。

修正内容

修正箇所だけ抜粋

input.blade.php
<form action="/upload/csv" method="post" enctype="multipart/form-data">

〜〜省略〜〜

</form>

原因その2

二つ目のエラーメッセージを見ると拡張子(.csv)が認識されていない?
この仕組みは深く追ってないですが、どうやらmimesルールの引数にはtxtも渡さないといけないようです。
そうすると「.txt」ファイルも許可することになりそうだけど、今回は妥協しました。

修正内容

修正箇所だけ抜粋

CsvUploadRequest.php
〜〜省略〜〜

    public function rules()
    {
        return [
            'csv_file' => 'required|file|mimes:csv,txt',
        ];
    }

〜〜省略〜〜

参考記事