Encodera

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.

Оглавление

Загрузка и хранение файлов

Аватары, фотографии товаров, вложения — почти в каждом приложении пользователи загружают файлы. Laravel берёт на себя проверку, выбор имени и сохранение, а код не зависит от того, лежат файлы на сервере или в облачном хранилище.

Форма

Форме нужен атрибут enctype:

<form method="POST" action="/avatar" enctype="multipart/form-data">
    @csrf
    <input type="file" name="avatar">
    <button type="submit">Загрузить</button>
</form>

Проверка и сохранение

Файл проверяют теми же правилами валидации, что и остальные поля. Метод store() сам придумывает случайное имя и возвращает путь:

public function update(Request $request)
{
    $request->validate([
        'avatar' => 'required|image|max:2048',
    ]);
 
    $path = $request->file('avatar')->store('avatars', 'public');
 
    $request->user()->update(['avatar' => $path]);
 
    return back()->with('status', 'Аватар обновлён');
}

Правило image проверяет содержимое файла, max:2048 — размер в килобайтах. В базе сохраняют только путь, например avatars/Hk3f9a.jpg.

Диски

Диск — это место хранения. Они описаны в config/filesystems.php:

ДискГде лежат файлыДоступ из браузера
localstorage/app/privateНет
publicstorage/app/publicДа, после создания ссылки
s3Облачное хранилищеПо настройкам хранилища

Чтобы файлы диска public открывались в браузере, один раз создают ссылку из папки public:

php artisan storage:link

Ссылка на файл

Фасад Storage возвращает адрес файла:

use Illuminate\Support\Facades\Storage;
 
$url = Storage::disk('public')->url($user->avatar);
<img src="{{ Storage::disk('public')->url($user->avatar) }}" alt="Аватар">

Другие действия

Storage::disk('public')->put('notes/today.txt', 'Текст заметки');
 
$text = Storage::disk('public')->get('notes/today.txt');
$exists = Storage::disk('public')->exists('notes/today.txt');
 
Storage::disk('public')->delete($user->avatar);

Скачивание закрытого файла

Файлы, которые нельзя отдавать всем подряд, хранят на диске local и отдают через контроллер после проверки прав:

public function download(Invoice $invoice)
{
    abort_unless($invoice->user_id === auth()->id(), 403);
 
    return Storage::download($invoice->file_path);
}

Частая ошибка

При замене файла старый остаётся на диске, и хранилище постепенно заполняется мусором. Удаляйте прежний файл перед сохранением нового:

if ($user->avatar) {
    Storage::disk('public')->delete($user->avatar);
}
 
$user->update(['avatar' => $request->file('avatar')->store('avatars', 'public')]);

Спасибо, что читаете!

Пожертвуйте сайту, мы стараемся ради вас.