ファイルアップロードの応用——画像リサイズ・複数ファイル・S3連携
FileUploadの基本おさらい
FilamentのFileUploadコンポーネントはLivewireのファイルアップロード機能をベースにしており、ドラッグ&ドロップ対応・プレビュー付きのUIが標準で提供されます。
use Filament\Forms\Components\FileUpload;
FileUpload::make('thumbnail')
->label('サムネイル')
->image()
->disk('public')
->directory('posts/thumbnails')
->visibility('public')
画像リサイズの設定
FileUpload::make('avatar')
->label('アバター画像')
->image()
->imageEditor() // ブラウザ内で画像を編集(トリミング可能)
->imageEditorAspectRatios([
null, // フリー
'1:1', // 正方形
'16:9', // ワイドスクリーン
'4:3', // 標準
])
->imageCropAspectRatio('1:1') // デフォルトのアスペクト比
->imageResizeTargetWidth(400) // リサイズ後の幅(px)
->imageResizeTargetHeight(400) // リサイズ後の高さ(px)
->imageResizeMode('cover') // cover | contain | force
->maxSize(2048) // 最大ファイルサイズ(KB)
->acceptedFileTypes(['image/jpeg', 'image/png', 'image/webp'])
->imageEditor()を有効にするとアップロード後に画像の切り抜きや回転ができるUIが表示されます。
複数ファイルのアップロード
FileUpload::make('product_images')
->label('商品画像')
->image()
->multiple()
->maxFiles(8)
->minFiles(1)
->reorderable() // ドラッグで並び替え可能
->appendFiles() // 既存ファイルに追加(上書きではなく)
->downloadable() // ダウンロードボタンを表示
->openable() // 別タブで開くボタンを表示
->disk('public')
->directory('products/images')
->imageResizeTargetWidth(1200)
->imageResizeTargetHeight(900)
複数ファイルの値はJSON配列でDBに保存されます。モデルのキャストを設定してください。
// app/Models/Product.php
protected $casts = [
'product_images' => 'array',
];
S3へのアップロード設定
.envにS3の設定を追加します。
AWS_ACCESS_KEY_ID=your-key-id
AWS_SECRET_ACCESS_KEY=your-secret-key
AWS_DEFAULT_REGION=ap-northeast-1
AWS_BUCKET=your-bucket-name
AWS_URL=https://your-bucket.s3.ap-northeast-1.amazonaws.com
config/filesystems.phpでS3ディスクを設定します(Laravelデフォルトで含まれています)。
FileUpload::make('document')
->label('ドキュメント')
->disk('s3') // S3ディスクを指定
->directory('documents')
->visibility('private') // 非公開ファイルの場合
->acceptedFileTypes([
'application/pdf',
'application/msword',
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
])
->maxSize(10240) // 10MB
->downloadable()
プライベートファイルのダウンロードには署名付きURLが必要です。
// モデルのアクセサでS3署名付きURLを生成
public function getDocumentUrlAttribute(): ?string
{
if (! $this->document) {
return null;
}
return Storage::disk('s3')->temporaryUrl(
$this->document,
now()->addMinutes(30)
);
}
Spatie MediaLibraryとの連携
より高度なメディア管理が必要な場合はspatie/laravel-medialibraryとの連携プラグインを使います。
composer require filament/spatie-laravel-media-library-plugin
php artisan media-library:install
モデルにInteractsWithMediaトレイトを追加します。
// app/Models/Post.php
use Spatie\MediaLibrary\HasMedia;
use Spatie\MediaLibrary\InteractsWithMedia;
use Spatie\MediaLibrary\MediaCollections\Models\Media;
class Post extends Model implements HasMedia
{
use InteractsWithMedia;
public function registerMediaCollections(): void
{
$this->addMediaCollection('thumbnail')
->singleFile() // 1ファイルのみ
->acceptsMimeTypes(['image/jpeg', 'image/png', 'image/webp']);
$this->addMediaCollection('gallery')
->acceptsMimeTypes(['image/jpeg', 'image/png']);
}
public function registerMediaConversions(?Media $media = null): void
{
$this->addMediaConversion('thumb')
->width(400)
->height(300)
->sharpen(10);
$this->addMediaConversion('large')
->width(1200)
->height(900);
}
}
フォームでSpatieMediaLibraryFileUploadを使います。
use Filament\Forms\Components\SpatieMediaLibraryFileUpload;
SpatieMediaLibraryFileUpload::make('thumbnail')
->label('サムネイル')
->collection('thumbnail') // MediaCollectionの名前
->image()
->imageEditor()
->conversion('thumb'), // プレビューにサムネイル変換を使用
SpatieMediaLibraryFileUpload::make('gallery')
->label('ギャラリー')
->collection('gallery')
->multiple()
->reorderable()
->maxFiles(10),
ファイルアップロードのバリデーション
FileUpload::make('resume')
->label('履歴書(PDF)')
->acceptedFileTypes(['application/pdf'])
->maxSize(5120) // 5MB
->rules([
'file',
'mimetypes:application/pdf',
'max:5120',
])
アップロード時のファイル名カスタマイズ
FileUpload::make('document')
->getUploadedFileNameForStorageUsing(
fn (TemporaryUploadedFile $file, callable $get): string =>
Str::slug($get('title')) . '-' . now()->format('YmdHis') . '.' . $file->getClientOriginalExtension()
)
コツ・注意点・ハマりポイント
コツ: ->storeFileNamesIn('original_filenames')を使うと元のファイル名を別カラムに保存できます。ユーザーが元のファイル名でダウンロードできるように保持したい場合に有用です。
注意点: S3にプライベートファイルをアップロードする場合、FilamentのデフォルトのプレビューURLはS3の公開URLを使おうとします。プライベートファイルのプレビューには->getUploadedFileUrlUsing()で署名付きURLを返すカスタマイズが必要です。
ハマりポイント: Livewireのファイルアップロードは一時的にstorage/app/livewire-tmp/に保存されます。フォームを送信しないとstorage/app/public/への移動が行われません。フォームキャンセル時に一時ファイルが残り続けるため、php artisan livewire:cleanupや定期Cronでの一時ファイルクリーニングを設定してください。
まとめ
FilamentのFileUploadはブラウザ内画像編集・複数ファイル・S3ストレージまで幅広くカバーしています。Spatie MediaLibraryプラグインと組み合わせると、複数サイズのサムネイル自動生成・コレクション管理・並び替えなど本格的なメディア管理が実現できます。