LoginSignup
5
5

More than 1 year has passed since last update.

Laravel での ajax を利用したファイルアップロード

Posted at

はじめに

Laravelを使っている案件でファイルアップロードを行う機会があったので、実装方法を記します。
なぜajaxを利用したかというと、編集画面というフォームの中でファイルアップロード機能を実装したかったから(編集画面で画面遷移することなくファイルアップロードのみ行いたかったから)

HTML

<div>
    <label for="" class="">ファイルのアップロード</label>
    <div class="">
        <input type="file" class="" id="upload_file" name="upload_file" accept="pdf, xlsx" style=''>
    </div>
    <input type="button" value="アップロード" id="upload" data-toggle="modal" data-target="#file_upload_modal" class="" style=''>
</div>

@component('includes.popup_modal', ['id' => 'file_upload_modal'])
    @slot('title')
        ファイルのアップロード
    @endslot
    @slot('body')
        ファイルのアップロード
        <label style="" class="" id="searchErrorMessage"></label>
    @endslot
    @slot('footer')
        <button type="button" id="file_upload_btn" class="">アップロード</button>
        <button type="button" class="" data-dismiss="modal">キャンセル</button>
    @endslot
@endcomponent

アップロードボタンをクリックするとモーダルを表示して「アップロード」ボタンを選択する事でアップロード処理を行います。
モーダルは別ファイルで管理しています。

ajax

<script>
$(document).ready(function () {
    $('#file_upload_btn').on('click', function() {

        //ajaxでのcsrfトークン送信
        $.ajaxSetup({
            headers: {
                'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
            }
        });

        //アップロードするファイルのデータ取得
        var fileData = document.getElementById("upload_file").files[0];
        //フォームデータを作成する
        var form = new FormData();
        //フォームデータにアップロードファイルの情報追加
        form.append("file", fileData);
        $.ajax({
            type: "POST",
            url: "{{ route('ajax_file_upload', ['id' => $id']) }}",
            data: form,
            processData: false,
            contentType: false,
            success: function (response) {
                if(response.is_success) {
                    //モーダルの処理
                    //エラーメッセージ非表示
                    $('#searchErrorMessage').html('');
                    $('#searchErrorMessage').hide();
                    //モーダルを閉じる
                    $('#file_upload_modal').modal('toggle');
                } else {
                    //モーダルでのエラーメッセージ表示処理
                    var msg = "";
                    $.each(response.errors_message, function (i, v) {
                        msg += v + "<br>";
                    });
                    $('#searchErrorMessage').html(msg);
                    $('#searchErrorMessage').show();
                }
            },
            error: function (response) {
                //エラー時の処理
            }
        });
    })
})
</script>
headers: {
    'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}

ここでCSRF保護のためcsrf-tokenをヘッダーに設定します。
これを行わないとエラーになります。
あとは

var form = new FormData();

フォームデータを作成してあげてこれを指定のControllerに渡します。

ここでは

url: "{{ route('ajax_file_upload', ['id' => $id']) }}",

ajax_file_upload というrouteに渡してます

PHP(LaravelのController)

Controllerでファイル情報を受け取ってサーバに保存します。

public function uploadFile(Request $request, $id){
    $response = [];

    //元ファイルのファイル名取得
    $fileName = $request->file('file')->getClientOriginalName();

    //拡張子チェック
    $ext = pathinfo($fileName)['extension'];
    $check_extension = ['xlsx', 'pdf'];
    if(!in_array($ext, $check_extension, true)){
        $response = [
            'is_success' => false,
            'errors_message' => ["エクセルファイルかPDFファイルのみアップロード可能です"]
        ];
        return response()->json($response);
    }
    //ファイル保存
    $upload_file_save = config('upload');
    $request->file('file')->storeAs($upload_file_save . $id, $fileName);

    $response = [
        'is_success' => true,
        'errors_message' => [""]
    ];

    return response()->json($response);
}
$fileName = $request->file('file')->getClientOriginalName();

getClientOriginalName で元のファイル名を取得できます。
※元ファイル名を利用しなかった場合はPHPが任意に決めたファイル名になります。

$response = [
    'is_success' => false,
    'errors_message' => ["エクセルファイルかPDFファイルのみアップロード可能です"]
];

エラーが起こった際に(この際は拡張子チェックでエラー)アップロードする際に確認を行ったモーダルにエラーメッセージを返します。

$upload_file_save = 'upload' . $id;
$request->file('file')->storeAs($upload_file_save, $fileName);

storeAs でファイル名の指定が可能です。ここではアップロードした元のファイル名。
また、アップロード先のディレクトリは指定しなければ storage/app となります
ここでは storage/app/upload/{$id} となります。

さいごに

これで最低限の実装は出来る、はず、です
間違いなどありましたらご指摘ください。

5
5
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
5
5