1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Laravel Inertia】ファイルのアップロードってできるんか?

Last updated at Posted at 2025-12-10

他に通信を行いたいことを考えると、ファイルのアップロードが思いつきますね。:thinking:

やってみる

では早速アップロード用の DTO を作成しましょう。

$ php artisan make:data FileUploadData

今回は、文字列と PDF をアップロードするフォームを考えます。
Laravel は MimeType とファイルサイズを指定できます。

アップロードしたファイルは IlluminateUploadFile というクラスに格納されるので、それを属性として登録しておきます。

app/Data/FileUploadData.php
namespace App\Data;

use Illuminate\Http\UploadedFile;
use Spatie\LaravelData\Attributes\Validation\File;
use Spatie\LaravelData\Attributes\Validation\Max;
use Spatie\LaravelData\Attributes\Validation\MimeTypes;
use Spatie\LaravelData\Data;
use Spatie\TypeScriptTransformer\Attributes\TypeScript;

#[TypeScript()]
class FileUploadData extends Data
{
    public function __construct(
        #[Max(255)]
        public string $text,
        #[File, MimeTypes('application/pdf'), Max(10 * 1024 * 1024)]
        public UploadedFile $image,
    ) {}
}

これをコントローラーで処理します。
任意の名前で保存する場合は Storage::putFileAs() を利用します。

第一引数がファイル名に見えますが、ここはディレクトリまでです。
ここに名前を付与すると <filename>/<hash>.ext という場所に保存されます。

ファイル名を付与したい場合は xxxAs 系のメソッドを使って第三引数に保存します!!!
(n敗)
ちなみにディレクトリは先に作成しておきましょう。

戻り値で保存先のフルパスが取得できます。

app/Http/Controllers/TestController.php
public function upload(FileUploadData $data)
{
    $path = Storage::putFileAs(
        '',
        $data->image,
        $data->image->getClientOriginalName(),
    );

    dd([
        'path' => $path,
        'data' => $data,
    ]);
}

画面側は、こんな感じにしてみました。

PrimeVue では FileUpload コンポーネントに上がってきた File オブジェクトを手動で useForm に渡すことで実現しています。
<input type="file"> の場合は、同じような形で File オブジェクトをハンドリングすればOKです。

<template>
  <form class="m-4 grid grid-cols-1 gap-2" @submit.prevent>
    <div class="grid grid-cols-1">
      <label>テキスト</label>
      <InputText v-model="form.text"/>
      <small class="text-red-500">{{ form.errors.text }}</small>
    </div>

    <div class="grid grid-cols-1">
      <label>PDFアップロード</label>
      <div class="flex items-center gap-2">
        <FileUpload
          mode="basic"
          @select="onFileSelect"
          customUpload
          auto
          severity="secondary"
          chooseLabel="PDFアップロード"
          class="p-button-outlined"
        />
        <small>{{ form.image?.name }}</small>
      </div>
      <small class="text-red-500">{{ form.errors.text }}</small>
    </div>

    <div>
      <Button label="送信" @click="onSubmit" />
    </div>
  </form>
</template>

<script setup lang="ts">
import { useForm } from '@inertiajs/vue3'

import Button from 'primevue/button'
import InputText from 'primevue/inputtext'
import FileUpload, { FileUploadSelectEvent } from 'primevue/fileupload'

import { upload } from '@/routes/tests'

const form = useForm<App.Data.FileUploadData>({
  text: '',
  image: undefined,
})

const onFileSelect = (e: FileUploadSelectEvent) => {
  form.image = e.files[0]
}

const onSubmit = () => {
  form.submit(upload())
}
</script>

image.png

では動かしで見ましょう!

アップロードしてみる

ボタンを押して、 Windows のファイル選択ダイアログから PDF ファイルを選択します。

image.png

これらは、File オブジェクトとして useForm に登録されます。
File は以下のようなデータが取得できるので、form.image?.name などと書くと画面上にファイルの内容を表示することができます。
上手くやれば画像表示とかもできますよ!

image.png

そして「送信ボタン」を押すと、、、
ファイルの保存に成功します!ワーイ!

image.png

image.png

終わりに

面倒なファイル送信も、Inerita.ja が適当にラップしてくれるんですよねぇ。

この通信は自動的に multipart/form-data; で送ってくれます。
なので、 base64 にしようか... `バイナリで投げつけようか.. などは何も考えなくてOKです。

image.png

ただこの記事で説明したのは、ファイルのアップロードの方法のみです。
データベースとの連携や、ファイルのトランザクションは他の方の記事などを読んでしっかり組みましょう。
データベースの範囲内であれば良しなにやってくれますが、ファイルは別空間での管理を余儀なくされますからね。。。

世の中やべーことになってるシステムはたくさんあります。:joy:
お気をつけて!

1
0
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?