Компонент з трейтом WithFileUploads приймає файли через звичайний wire:model:
use Livewire\WithFileUploads;
new class extends Component {
use WithFileUploads;
#[Validate('image|max:2048')] // 2 МБ
public $photo;
public function save(): void
{
$this->validate();
$path = $this->photo->store(path: 'avatars', options: 'public');
auth()->user()->update(['avatar_path' => $path]);
}
};
<input type="file" wire:model="photo">
@if ($photo) <img src="{{ $photo->temporaryUrl() }}"> @endif
Як це працює під капотом:
- при виборі файлу JavaScript запитує в компонента підписаний URL для завантаження;
- файл завантажується за ним у тимчасовий каталог (
livewire-tmp/на диску за замовчуванням); - властивість
$photoотримує об'єкт тимчасового файлу (TemporaryUploadedFile); - у вашому методі файл перевіряється й переноситься на постійне місце.
Ризики й захист:
- глобальна валідація тимчасових завантажень - за замовчуванням
file|max:12288(12 МБ). Тобто ще до вашої валідації сервер приймає будь-який файл до 12 МБ. Звузьте вconfig/livewire.php(temporary_file_upload.rules), якщо застосунку не потрібні великі файли; - обмеження частоти - ендпойнт завантаження за замовчуванням має throttle-middleware; його можна змінити (
temporary_file_upload.middleware). Але в Livewire 4 файли понад 1 МБ на локальному диску йдуть частинами (chunked upload) - один файл стає десятками швидких запитів. Надто жорсткий ліміт на кшталтthrottle:60,1ламає великі завантаження; - розмір файлу обмежує ваше правило
max:, а неupload_max_filesizePHP: частини збираються на сервері, і перерване завантаження продовжується з місця зупинки; - перевірка типу - лише через правила валідації (
image,mimes:pdf), які перевіряють вміст, а не розширення. Ніколи не зберігайте з оригінальною назвою від користувача без перевірки - використовуйте згенеровану (store()робить саме так); - попередній перегляд (
temporaryUrl()) працює лише для зображень і через підписаний URL - чужі файли так не подивитися; - очищення - на локальному диску Livewire сам видаляє старі тимчасові файли; для S3 треба налаштувати правило життєвого циклу (
php artisan livewire:configure-s3-upload-cleanup, файли старші 24 годин); - публічність - зберігайте в приватний диск усе, що не призначене для всіх, і віддавайте через підписані URL.
Пряме завантаження в S3 (LIVEWIRE_TEMPORARY_FILE_UPLOAD_DISK=s3) знімає навантаження з сервера застосунку: файл іде з браузера одразу в бакет. Але частина правил валідації потребує доступу до файлу - бакет має це дозволяти.
Пастка з назвою: upload - зарезервоване слово Livewire. Метод чи властивість з такою назвою зламають завантаження.
Тести: UploadedFile::fake()->image('avatar.jpg') з ->set('photo', $file) і Storage::fake().