Урок 11: Файлы и хранилище в Laravel

В 11-ом уроке мы погрузимся в работу с файлами и хранилищем в Laravel. Это важная тема, ведь почти каждое веб-приложение так или иначе взаимодействует с файлами, загружает аватарки, сохраняет документы или обрабатывает изображения. В этом уроке я расскажу, как правильно работать с файлами, куда их сохранять и как обеспечить к ним безопасный доступ.

Загрузка файлов через формы

Первое, с чем мы сталкиваемся при работе с файлами, это их загрузка через HTML-формы. В Laravel это делается просто, но есть нюансы, о которых важно знать.

Шаг 1: Создание формы для загрузки

Допустим, мы хотим создать форму для загрузки аватара пользователя. Вот как это выглядит в Blade:

html
<!-- resources/views/profile/avatar.blade.php -->
<form method="POST" action="{{ route('avatar.upload') }}" enctype="multipart/form-data">
    @csrf
    <input type="file" name="avatar" required>
    <button type="submit">Загрузить аватар</button>
</form>

Атрибут enctype="multipart/form-data" обязателен для загрузки файлов. Без него файл не будет отправлен на сервер.

Шаг 2: Обработка файла в контроллере

Создадим контроллер AvatarController и метод upload:

bash
php artisan make:controller AvatarController

В методе upload мы получим файл из запроса:

php
// app/Http/Controllers/AvatarController.php
public function upload(Request $request) {
    // Валидация файла
    $request->validate([
        'avatar' => 'required|file|image|max:2048', // Максимум 2 МБ
    ]);

    // Получаем файл
    $file = $request->file('avatar');

    // Сохраняем файл (об этом ниже)
    $path = $file->store('avatars');

    // Сохраняем путь к файлу в БД (пример)
    auth()->user()->update(['avatar_path' => $path]);

    return redirect()->back()->with('success', 'Аватар успешно загружен!');
}

Сохранение файлов в storage/app

Laravel использует систему хранилищ (Storage) для работы с файлами. По умолчанию файлы сохраняются в storage/app. Это безопасно, так как эта папка недоступна извне (в отличие от public).

Как сохранить файл?

Используйте метод store(), как в примере выше, или явно укажите диск:

php
$path = $file->store(
    'avatars', // Папка внутри storage/app
    'local'    // Имя диска (по умолчанию 'local')
);

Структура storage/app

  • storage/app/avatars — ваши загруженные файлы.
  • storage/app/public — файлы, которые должны быть доступны публично (например, через браузер).
  • storage/app/private — закрытые файлы (требуют аутентификацию).

Создание символической ссылки (storage:link)

Файлы в storage/app по умолчанию недоступны извне. Чтобы сделать их публичными, нужно создать символическую ссылку из public/storage в storage/app/public.

Как это сделать?

Запустите команду:

bash
php artisan storage:link

Теперь все файлы, сохраненные в storage/app/public, будут доступны по URL:

http://ваш-сайт/storage/имя-файла.jpg

Если вы работаете на Windows, убедитесь что ваша система поддерживает символические ссылки или используйте WSL.

Генерация URL для файлов

Чтобы получить URL файла, используйте фасад Storage:

php
use Illuminate\Support\Facades\Storage;

// Для файла в storage/app/public
$url = Storage::url('имя-файла.jpg'); 
// Вернет: /storage/имя-файла.jpg

// Для файла в storage/app/avatars (не в public!)
$url = Storage::disk('local')->url('avatars/файл.jpg');
// Но это сработает только, если настроен соответствующий маршрут.

Файлы вне storage/app/public не будут доступны через браузер, если вы не создадите для них специальный маршрут.

Практические задачи

Задача 1: Загрузка аватара

  1. Создайте форму для загрузки аватара.
  2. Реализуйте валидацию: только изображения до 2 МБ.
  3. Сохраните файл в storage/app/public/avatars.
  4. Выведите загруженный аватар на странице профиля.

Решение:

php
// В контроллере
$path = $request->file('avatar')->store('public/avatars');
// В Blade
<img src="{{ Storage::url(str_replace('public/', '', $path)) }}" alt="Аватар">

Задача 2: Создайте галерею изображений

Позвольте пользователям загружать несколько изображений и выводите их в виде сетки.

Подсказка:

php
// Для загрузки нескольких файлов
$files = $request->file('images');
foreach ($files as $file) {
    $file->store('public/gallery');
}

Частые ошибки

  1. Забыли enctype="multipart/form-data" — файл не загрузится.
  2. Пытаются получить доступ к storage/app напрямую — используйте storage:link.
  3. Не проверяют тип файла — злоумышленник может загрузить скрипт вместо изображения.

Хотите освоить Laravel быстрее? Перейти к полному курсу по Laravel для начинающих