ファイルアップロード
Livewireは、コンポーネント内でのファイルアップロードのための強力なサポートを提供します。Livewire offers powerful support for uploading files within your components.
まず、コンポーネントに WithFileUploads
トレイトを追加します。このトレイトがコンポーネントに追加されると、まるで他の入力タイプであるかのように、ファイル入力に wire:model
を使用できます。Livewireが残りの処理を行います。First, add the WithFileUploads
trait to your component. Once this trait has been added to your component, you can use wire:model
on file inputs as if they were any other input type and Livewire will take care of the rest.
以下は、写真をアップロードする簡単なコンポーネントの例です。Here's an example of a simple component that handles uploading a photo:
<?php
namespace App\Livewire;
use Livewire\Component;
use Livewire\WithFileUploads;
use Livewire\Attributes\Validate;
class UploadPhoto extends Component
{
use WithFileUploads;
#[Validate('image|max:1024')] // 1MB Max
public $photo;
public function save()
{
$this->photo->store(path: 'photos');
}
}
<form wire:submit="save">
<input type="file" wire:model="photo">
@error('photo') <span class="error">{{ $message }}</span> @enderror
<button type="submit">写真を保存</button>
</form>
[!warning] The "upload" method is reserved Notice the above example uses a "save" method instead of an "upload" method. This is a common "gotcha". The term "upload" is reserved by Livewire. You cannot use it as a method or property name in your component.
Warning! "upload" メソッドは予約されています 上記の例では、"upload" メソッドの代わりに "save" メソッドを使用していることに注意してください。これはよくある「落とし穴」です。"upload" という用語はLivewireによって予約されています。コンポーネント内でメソッドまたはプロパティ名として使用することはできません。
開発者の視点から見ると、ファイル入力の処理は他の入力タイプの処理と変わりません。<input>
タグに wire:model
を追加するだけで、残りの処理はすべて自動的に行われます。From the developer's perspective, handling file inputs is no different than handling any other input type: Add wire:model
to the <input>
tag and everything else is taken care of for you.
ただし、Livewireでファイルアップロードを機能させるためには、内部でより多くの処理が行われています。ユーザーがアップロードするファイルを選択したときに何が起こるかの概要を以下に示します。However, more is happening under the hood to make file uploads work in Livewire. Here's a glimpse at what goes on when a user selects a file to upload:
- 新しいファイルが選択されると、LivewireのJavaScriptは、一時的な「署名付き」アップロードURLを取得するために、サーバ上のコンポーネントに最初のリクエストを送信します。When a new file is selected, Livewire's JavaScript makes an initial request to the component on the server to get a temporary "signed" upload URL.
- URLを受信すると、JavaScriptは署名付きURLへの実際の「アップロード」を実行し、Livewireによって指定された一時ディレクトリにアップロードを保存し、新しい一時ファイルのユニークなハッシュIDを返します。Once the URL is received, JavaScript does the actual "upload" to the signed URL, storing the upload in a temporary directory designated by Livewire and returning the new temporary file's unique hash ID.
- ファイルがアップロードされ、ユニークなハッシュIDが生成されると、LivewireのJavaScriptはサーバ上のコンポーネントに最終リクエストを送信し、目的のパブリックプロパティを新しい一時ファイルに「設定」するように指示します。Once the file is uploaded and the unique hash ID is generated, Livewire's JavaScript makes a final request to the component on the server, telling it to "set" the desired public property to the new temporary file.
- これで、パブリックプロパティ(この場合は
$photo
)は一時ファイルアップロードに設定され、いつでも保存または検証できるようになります。Now, the public property (in this case,$photo
) is set to the temporary file upload and is ready to be stored or validated at any point.
アップロードされたファイルの保存Storing uploaded files
前の例では、最も基本的な保存シナリオを示しています。一時的にアップロードされたファイルを、アプリケーションのデフォルトのファイルシステムディスクの「photos」ディレクトリに移動します。The previous example demonstrates the most basic storage scenario: moving the temporarily uploaded file to the "photos" directory on the application's default filesystem disk.
ただし、保存されたファイルの名前をカスタマイズしたり、ファイルを保持する特定のストレージ「ディスク」(S3など)を指定したりすることもできます。However, you may want to customize the file name of the stored file or even specify a specific storage "disk" to keep the file on (such as S3).
Tip: 元のファイル名 一時的なアップロードの元のファイル名には、
->getClientOriginalName()
メソッドを呼び出すことでアクセスできます。[!tip] Original file names You can access the original file name of a temporary upload, by calling its->getClientOriginalName()
method.
Livewireは、Laravelがアップロードされたファイルを保存するために使用するのと同じAPIを尊重するため、Laravelのファイルアップロードに関するドキュメントを参照してください。ただし、以下にいくつかの一般的なストレージシナリオと例を示します。Livewire honors the same APIs Laravel uses for storing uploaded files, so feel free to consult Laravel's file upload documentation[https://laravel.com/docs/filesystem#file-uploads]. However, below are a few common storage scenarios and examples:
public function save()
{
// デフォルトのファイルシステムディスクの「photos」ディレクトリにファイルを保存します
$this->photo->store(path: 'photos');
// 設定された「s3」ディスクの「photos」ディレクトリにファイルを保存します
$this->photo->store(path: 'photos', options: 's3');
// ファイルを「avatar.png」というファイル名で「photos」ディレクトリに保存します
$this->photo->storeAs(path: 'photos', name: 'avatar');
// 設定された「s3」ディスクに「avatar.png」というファイル名で「photos」ディレクトリにファイルを保存します
$this->photo->storeAs(path: 'photos', name: 'avatar', options: 's3');
// 設定された「s3」ディスクで「public」な可視性を持つ「photos」ディレクトリにファイルを保存します
$this->photo->storePublicly(path: 'photos', options: 's3');
// 「avatar.png」という名前で、「public」な可視性を持つ、設定された「s3」ディスクの「photos」ディレクトリにファイルを保存します
$this->photo->storePubliclyAs(path: 'photos', name: 'avatar', options: 's3');
}
複数のファイルの処理Handling multiple files
Livewireは、<input>
タグの multiple
属性を検出することで、複数のファイルアップロードを自動的に処理します。Livewire automatically handles multiple file uploads by detecting the multiple
attribute on the <input>
tag.
たとえば、以下は $photos
という名前の配列プロパティを持つコンポーネントです。フォームのファイル入力に multiple
を追加すると、Livewireは自動的に新しいファイルをこの配列に追加します。For example, below is a component with an array property named $photos
. By adding multiple
to the form's file input, Livewire will automatically append new files to this array:
use Livewire\Component;
use Livewire\WithFileUploads;
use Livewire\Attributes\Validate;
class UploadPhotos extends Component
{
use WithFileUploads;
#[Validate(['photos.*' => 'image|max:1024'])]
public $photos = [];
public function save()
{
foreach ($this->photos as $photo) {
$photo->store(path: 'photos');
}
}
}
<form wire:submit="save">
<input type="file" wire:model="photos" multiple>
@error('photos.*') <span class="error">{{ $message }}</span> @enderror
<button type="submit">写真を保存</button>
</form>
ファイルのバリデーションFile validation
すでに説明したように、Livewireでのファイルアップロードのバリデーションは、標準のLaravelコントローラーからのファイルアップロードの処理と同じです。Like we've discussed, validating file uploads with Livewire is the same as handling file uploads from a standard Laravel controller.
S3に直接アップロードする場合、S3ファイルオブジェクトがパブリックにアクセスできない場合、これらのバリデーションルールは失敗します。[!warning] Ensure S3 is properly configured Many of the validation rules relating to files require access to the file. When uploading directly to S3[#uploading-directly-to-amazon-s3], these validation rules will fail if the S3 file object is not publicly accessible.
Warning! S3が適切に設定されていることを確認してください ファイルに関連するバリデーションルールの多くは、ファイルへのアクセスが必要です。
ファイルバリデーションの詳細については、Laravelのファイルバリデーションに関するドキュメントを参照してください。For more information on file validation, consult Laravel's file validation documentation[https://laravel.com/docs/validation#available-validation-rules].
一時プレビューURLTemporary preview URLs
ユーザーがファイルを選択した後、通常はフォームを送信してファイルを保存する前に、そのファイルのプレビューを表示する必要があります。After a user chooses a file, you should typically show them a preview of that file before they submit the form and store the file.
Livewireは、アップロードされたファイルの ->temporaryUrl()
メソッドを使用することで、これを簡単に実現します。Livewire makes this trivial by using the ->temporaryUrl()
method on uploaded files.
[!info] Temporary URLs are restricted to images For security reasons, temporary preview URLs are only supported on files with image MIME types.
Info: 一時URLは画像に制限されています セキュリティ上の理由から、一時プレビューURLは、画像MIMEタイプを持つファイルでのみサポートされています。
画像プレビューを使用したファイルアップロードの例を見てみましょう。Let's explore an example of a file upload with an image preview:
use Livewire\Component;
use Livewire\WithFileUploads;
use Livewire\Attributes\Validate;
class UploadPhoto extends Component
{
use WithFileUploads;
#[Validate('image|max:1024')]
public $photo;
// ...
}
<form wire:submit="save">
@if ($photo) <!-- [tl! highlight:2] -->
<img src="{{ $photo->temporaryUrl() }}">
@endif
<input type="file" wire:model="photo">
@error('photo') <span class="error">{{ $message }}</span> @enderror
<button type="submit">写真を保存</button>
</form>
すでに説明したように、Livewireは一時ファイルを非公開ディレクトリに保存します。したがって、通常、一時的なパブリックURLをユーザーに公開して画像のプレビューを表示する簡単な方法はありません。As previously discussed, Livewire stores temporary files in a non-public directory; therefore, typically there's no simple way to expose a temporary, public URL to your users for image previewing.
ただし、Livewireは、アップロードされた画像であるかのように装う一時的な署名付きURLを提供することで、この問題を解決します。これにより、ページはユーザーに画像のプレビューを表示できます。However, Livewire solves this issue by providing a temporary, signed URL that pretends to be the uploaded image so your page can show an image preview to your users.
このURLは、一時ディレクトリより上のディレクトリのファイルを表示しないように保護されています。また、署名されているため、ユーザーはこのURLを悪用してシステム上の他のファイルをプレビューすることはできません。This URL is protected against showing files in directories above the temporary directory. And, because it's signed, users can't abuse this URL to preview other files on your system.
Tip: S3一時署名付きURL Livewireが一時ファイルストレージにS3を使用するように設定している場合、
->temporaryUrl()
を呼び出すと、Laravelアプリケーションサーバから画像プレビューがロードされないように、S3への一時的な署名付きURLが直接生成されます。[!tip] S3 temporary signed URLs If you've configured Livewire to use S3 for temporary file storage, calling->temporaryUrl()
will generate a temporary, signed URL to S3 directly so that image previews aren't loaded from your Laravel application server.
ファイルアップロードのテストTesting file uploads
Laravelの既存のファイルアップロードテストヘルパを使用して、ファイルアップロードをテストできます。You can use Laravel's existing file upload testing helpers to test file uploads.
以下は、Livewireで UploadPhoto
コンポーネントをテストする完全な例です。Below is a complete example of testing the UploadPhoto
component with Livewire:
<?php
namespace Tests\Feature\Livewire;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use App\Livewire\UploadPhoto;
use Livewire\Livewire;
use Tests\TestCase;
class UploadPhotoTest extends TestCase
{
public function test_can_upload_photo()
{
Storage::fake('avatars');
$file = UploadedFile::fake()->image('avatar.png');
Livewire::test(UploadPhoto::class)
->set('photo', $file)
->call('upload', 'uploaded-avatar.png');
Storage::disk('avatars')->assertExists('uploaded-avatar.png');
}
}
以下は、上記のテストに合格するために必要な UploadPhoto
コンポーネントの例です。Below is an example of the UploadPhoto
component required to make the previous test pass:
use Livewire\Component;
use Livewire\WithFileUploads;
class UploadPhoto extends Component
{
use WithFileUploads;
public $photo;
public function upload($name)
{
$this->photo->storeAs('/', $name, disk: 'avatars');
}
// ...
}
ファイルアップロードのテストの詳細については、Laravelのファイルアップロードテストに関するドキュメントを参照してください。For more information on testing file uploads, please consult Laravel's file upload testing documentation[https://laravel.com/docs/http-tests#testing-file-uploads].
Amazon S3への直接アップロードUploading directly to Amazon S3
すでに説明したように、Livewireはすべてのファイルアップロードを、開発者がファイルを永続的に保存するまで一時ディレクトリに保存します。As previously discussed, Livewire stores all file uploads in a temporary directory until the developer permanently stores the file.
デフォルトでは、Livewireはデフォルトのファイルシステムディスク構成(通常は local
)を使用し、livewire-tmp/
ディレクトリ内にファイルを保存します。By default, Livewire uses the default filesystem disk configuration (usually local
) and stores the files within a livewire-tmp/
directory.
したがって、アップロードされたファイルを後でS3バケットに保存することを選択した場合でも、ファイルアップロードは常にアプリケーションサーバを利用しています。Consequently, file uploads are always utilizing your application server, even if you choose to store the uploaded files in an S3 bucket later.
アプリケーションサーバをバイパスして、Livewireの一時アップロードをS3バケットに保存する場合は、アプリケーションの config/livewire.php
構成ファイルでその動作を構成できます。最初に、livewire.temporary_file_upload.disk
を s3
(または s3
ドライバーを使用する別のカスタムディスク)に設定します。If you wish to bypass your application server and instead store Livewire's temporary uploads in an S3 bucket, you can configure that behavior in your application's config/livewire.php
configuration file. First, set livewire.temporary_file_upload.disk
to s3
(or another custom disk that uses the s3
driver):
return [
// ...
'temporary_file_upload' => [
'disk' => 's3',
// ...
],
];
これで、ユーザーがファイルをアップロードしても、ファイルは実際にはサーバに保存されません。代わりに、livewire-tmp/
サブディレクトリ内のS3バケットに直接アップロードされます。Now, when a user uploads a file, the file will never actually be stored on your server. Instead, it will be uploaded directly to your S3 bucket within the livewire-tmp/
sub-directory.
Info: Livewireの構成ファイルの発行 ファイルアップロードディスクをカスタマイズする前に、次のコマンドを実行して、Livewireの構成ファイルをアプリケーションの
/config
ディレクトリに最初に発行する必要があります。[!info] Publishing Livewire's configuration file Before customizing the file upload disk, you must first publish Livewire's configuration file to your application's/config
directory by running the following command:php artisan livewire:publish --config
自動ファイルクリーンアップの構成Configuring automatic file cleanup
Livewireの一時アップロードディレクトリはすぐにファイルでいっぱいになるため、24時間以上前のファイルをクリーンアップするようにS3を構成することが重要です。Livewire's temporary upload directory will fill up with files quickly; therefore, it's essential to configure S3 to clean up files older than 24 hours.
この動作を構成するには、ファイルアップロードにS3バケットを利用している環境から、次のArtisanコマンドを実行します。To configure this behavior, run the following Artisan command from the environment that is utilizing an S3 bucket for file uploads:
php artisan livewire:configure-s3-upload-cleanup
これで、24時間以上前の一時ファイルはすべてS3によって自動的にクリーンアップされます。Now, any temporary files older than 24 hours will be cleaned up by S3 automatically.
[!info] If you are not using S3 for file storage, Livewire will handle file cleanup automatically and there is no need to run the command above.
Info: ファイルストレージにS3を使用していない場合、Livewireはファイルクリーンアップを自動的に処理するため、上記のコマンドを実行する必要はありません。
ローディングインジケーターLoading indicators
ファイルアップロードの wire:model
は、他の wire:model
入力タイプとは異なり動作しますが、ローディングインジケーターを表示するためのインターフェイスは同じです。Although wire:model
for file uploads works differently than other wire:model
input types under the hood, the interface for showing loading indicators remains the same.
次のように、ファイルアップロードにスコープされたローディングインジケーターを表示できます。You can display a loading indicator scoped to the file upload like so:
<input type="file" wire:model="photo">
<div wire:loading wire:target="photo">アップロード中...</div>
これで、ファイルのアップロード中に「アップロード中...」というメッセージが表示され、アップロードが完了すると非表示になります。Now, while the file is uploading, the "Uploading..." message will be shown and then hidden when the upload is finished.
ローディング状態の詳細については、包括的なローディング状態に関するドキュメントを参照してください。For more information on loading states, check out our comprehensive loading state documentation[/docs/wire-loading].
Progress indicatorsProgress indicators
すべてのLivewireファイルアップロード操作は、対応する<input>
要素でJavaScriptイベントを発行し、カスタムJavaScriptがイベントを傍受できるようにします。Every Livewire file upload operation dispatches JavaScript events on the corresponding <input>
element, allowing custom JavaScript to intercept the events:
イベントEvent | 説明Description |
---|---|
livewire-upload-start livewire-upload-start |
アップロードが開始されたときに発行されますDispatched when the upload starts |
livewire-upload-finish livewire-upload-finish |
アップロードが正常に終了した場合に発行されますDispatched if the upload is successfully finished |
livewire-upload-cancel livewire-upload-cancel |
アップロードが途中でキャンセルされた場合に発行されますDispatched if the upload was cancelled prematurely |
livewire-upload-error livewire-upload-error |
アップロードが失敗した場合に発行されますDispatched if the upload fails |
livewire-upload-progress livewire-upload-progress |
アップロードの進行状況のパーセンテージを含むイベント(アップロードの進行に伴って発行されます)An event containing the upload progress percentage as the upload progresses |
以下は、アップロードの進行状況バーを表示するために、LivewireファイルアップロードをAlpineコンポーネントでラップする例です。Below is an example of wrapping a Livewire file upload in an Alpine component to display an upload progress bar:
<form wire:submit="save">
<div
x-data="{ uploading: false, progress: 0 }"
x-on:livewire-upload-start="uploading = true"
x-on:livewire-upload-finish="uploading = false"
x-on:livewire-upload-cancel="uploading = false"
x-on:livewire-upload-error="uploading = false"
x-on:livewire-upload-progress="progress = $event.detail.progress"
>
<!-- File Input -->
<input type="file" wire:model="photo">
<!-- Progress Bar -->
<div x-show="uploading">
<progress max="100" x-bind:value="progress"></progress>
</div>
</div>
<!-- ... -->
</form>
アップロードのキャンセルCancelling an upload
アップロードに時間がかかる場合、ユーザーはそれをキャンセルしたい場合があります。 Livewireの$cancelUpload()
関数をJavaScriptで使用して、この機能を提供できます。If an upload is taking a long time, a user may want to cancel it. You can provide this functionality with Livewire's $cancelUpload()
function in JavaScript.
以下は、wire:click
を使用してクリックイベントを処理するLivewireコンポーネントで、[キャンセルアップロード]ボタンを作成する例です。Here's an example of creating a "Cancel Upload" button in a Livewire component using wire:click
to handle the click event:
<form wire:submit="save">
<!-- File Input -->
<input type="file" wire:model="photo">
<!-- Cancel upload button -->
<button type="button" wire:click="$cancelUpload('photo')">Cancel Upload</button>
<!-- ... -->
</form>
「キャンセルアップロード」が押されると、ファイルアップロードリクエストは中止され、ファイル入力はクリアされます。 ユーザーは別のファイルで別のアップロードを試みることができるようになりました。When "Cancel upload" is pressed, the file upload will request will be aborted and the file input will be cleared. The user can now attempt another upload with a different file.
または、次のようにAlpineからcancelUpload(...)
を呼び出すこともできます。Alternatively, you can call cancelUpload(...)
from Alpine like so:
<button type="button" x-on:click="$wire.cancelUpload('photo')">Cancel Upload</button>
JavaScript upload APIJavaScript upload API
サードパーティのファイルアップロードライブラリとの統合には、単純な<input type="file" wire:model="...">
要素よりも多くの制御が必要になることがよくあります。Integrating with third-party file-uploading libraries often requires more control than a simple <input type="file" wire:model="...">
element.
これらのシナリオのために、Livewireは専用のJavaScript関数を公開します。For these scenarios, Livewire exposes dedicated JavaScript functions.
これらの関数はJavaScriptコンポーネントオブジェクトに存在し、Livewireコンポーネントのテンプレート内からLivewireの便利な$wire
オブジェクトを使用してアクセスできます。These functions exist on a JavaScript component object, which can be accessed using Livewire's convenient $wire
object from within your Livewire component's template:
@script
<script>
let file = $wire.el.querySelector('input[type="file"]').files[0]
// Upload a file...
$wire.upload('photo', file, (uploadedFilename) => {
// Success callback...
}, () => {
// Error callback...
}, (event) => {
// Progress callback...
// event.detail.progress contains a number between 1 and 100 as the upload progresses
}, () => {
// Cancelled callback...
})
// Upload multiple files...
$wire.uploadMultiple('photos', [file], successCallback, errorCallback, progressCallback, cancelledCallback)
// Remove single file from multiple uploaded files...
$wire.removeUpload('photos', uploadedFilename, successCallback)
// Cancel an upload...
$wire.cancelUpload('photos')
</script>
@endscript
設定Configuration
Livewireは、開発者が検証または保存できるようになる前に、すべてのファイルアップロードを一時的に保存するため、すべてのファイルアップロードに対していくつかのデフォルトの処理動作を想定しています。Because Livewire stores all file uploads temporarily before the developer can validate or store them, it assumes some default handling behavior for all file uploads.
グローバル検証Global validation
デフォルトでは、Livewireはすべての一時ファイルアップロードを次のルールで検証します:file|max:12288
(12MB未満のファイルである必要があります)。By default, Livewire will validate all temporary file uploads with the following rules: file|max:12288
(Must be a file less than 12MB).
これらのルールをカスタマイズする場合は、アプリケーションのconfig/livewire.php
ファイル内でそれを行うことができます。If you wish to customize these rules, you can do so inside your application's config/livewire.php
file:
'temporary_file_upload' => [
// ...
'rules' => 'file|mimes:png,jpg,pdf|max:102400', // (最大100MB、PNG、JPEG、およびPDFのみを受け入れます)
],
グローバルミドルウェアGlobal middleware
一時ファイルアップロードエンドポイントには、デフォルトでスロットリングミドルウェアが割り当てられています。 このエンドポイントが使用するミドルウェアを正確にカスタマイズするには、次の構成オプションを使用します。The temporary file upload endpoint is assigned a throttling middleware by default. You can customize exactly what middleware this endpoint uses via the following configuration option:
'temporary_file_upload' => [
// ...
'middleware' => 'throttle:5,1', // ユーザーごとに1分あたり5回のアップロードのみを許可します
],
一時アップロードディレクトリTemporary upload directory
一時ファイルは、指定されたディスクのlivewire-tmp/
ディレクトリにアップロードされます。 このディレクトリをカスタマイズするには、次の構成オプションを使用します。Temporary files are uploaded to the specified disk's livewire-tmp/
directory. You can customize this directory via the following configuration option:
'temporary_file_upload' => [
// ...
'directory' => 'tmp',
],