Урок 13: Работа с файлами в Symfony. Загрузка, облачное хранение, превью

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

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

Загрузка файлов частая задача веб-приложений. В Symfony это делается через форму с использованием компонента Form. Вот как это работает:

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

Добавим поле для загрузки файла в форму. Для этого используем тип FileType:

php
// src/Form/UploadFileType.php
namespace App\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;

class UploadFileType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('file', FileType::class, [
                'label' => 'Выберите файл',
            ])
            ->add('save', SubmitType::class, [
                'label' => 'Загрузить',
            ]);
    }
}

Шаг 2: Отображение формы в шаблоне

Важно не забыть добавить атрибут enctype="multipart/form-data" в форму, иначе файл не отправится:

twig
{# templates/upload/index.html.twig #}
{{ form_start(form, {'attr': {'enctype': 'multipart/form-data'}}) }}
{{ form_widget(form) }}
{{ form_end(form) }}

Шаг 3: Обработка загрузки в контроллере

Получим загруженный файл через объект UploadedFile:

php
// src/Controller/UploadController.php
namespace App\Controller;

use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use App\Form\UploadFileType;

class UploadController extends AbstractController
{
    public function upload(Request $request): Response
    {
        $form = $this->createForm(UploadFileType::class);
        $form->handleRequest($request);

        if ($form->isSubmitted() && $form->isValid()) {
            $file = $form->get('file')->getData();

            // Здесь будем обрабатывать файл
            return $this->redirectToRoute('upload_success');
        }

        return $this->render('upload/index.html.twig', [
            'form' => $form->createView(),
        ]);
    }
}

Использование UploadedFile

Объект UploadedFile предоставляет методы для работы с загруженным файлом. Например:

Валидация файла

Проверим размер и MIME-тип:

php
if ($file) {
    // Максимальный размер файла 5 МБ
    $maxSize = 5 * 1024 * 1024; 
    if ($file->getSize() > $maxSize) {
        throw new \Exception('Файл слишком большой!');
    }

    // Допустимые MIME-типы
    $allowedMimeTypes = ['image/jpeg', 'image/png', 'application/pdf'];
    if (!in_array($file->getMimeType(), $allowedMimeTypes)) {
        throw new \Exception('Недопустимый формат файла!');
    }
}

Сохранение файла

Переместим файл в директорию public/uploads:

php
$fileName = uniqid().'.'.$file->guessExtension();
$file->move(
    $this->getParameter('upload_directory'), // путь задан в services.yaml
    $fileName
);

Не забудьте добавить параметр в config/services.yaml:

yaml
parameters:
    upload_directory: '%kernel.project_dir%/public/uploads'

Хранение файлов в облаке (Amazon S3, Google Cloud)

Хранить файлы локально, не всегда лучший вариант. Для облачного хранения используем Flysystem:

Установка Flysystem

Подключим бандл для работы с облачными провайдерами:

bash
composer require league/flysystem-bundle

Настройка Amazon S3

Добавим конфигурацию в .env:

bash
AWS_ACCESS_KEY_ID=ваш_ключ
AWS_SECRET_ACCESS_KEY=ваш_секрет
AWS_BUCKET_NAME=имя_бакета

Настроим Flysystem в config/packages/flysystem.yaml:

yaml
flysystem:
    storages:
        s3_storage:
            adapter: 'aws'
            options:
                client: Aws\S3\S3Client
                bucket: '%env(AWS_BUCKET_NAME)%'

Загрузка файла в S3

Используем сервис s3_storage:

php
use League\Flysystem\Filesystem;

public function uploadToS3(Filesystem $s3Storage, UploadedFile $file)
{
    $stream = fopen($file->getRealPath(), 'r');
    $s3Storage->writeStream(
        'uploads/'.$file->getClientOriginalName(),
        $stream
    );
    fclose($stream);
}

Генерация превью изображений

Для работы с изображениями установим Imagine Bundle:

bash
composer require liip/imagine-bundle

Создание превью

Изменим размер изображения до 200×200 пикселей:

php
use Liip\ImagineBundle\Imagine\Cache\CacheManager;

public function generateThumbnail(CacheManager $cacheManager, string $imagePath)
{
    // Путь к оригинальному изображению
    $fullPath = $this->getParameter('upload_directory').'/'.$imagePath;

    // Генерируем превью
    $thumbnailPath = $cacheManager->getBrowserPath($imagePath, 'my_thumb');

    return $thumbnailPath;
}

Настроим фильтр в config/packages/liip_imagine.yaml:

yaml
liip_imagine:
    filter_sets:
        my_thumb:
            quality: 80
            filters:
                thumbnail: { size: [200, 200], mode: outbound }

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

  1. Задача 1: Создайте форму для загрузки аватара пользователя.
    Решение: Добавьте поле avatar типа FileType в форму регистрации.
  2. Задача 2: Реализуйте загрузку файлов в Google Cloud Storage.
    Подсказка: Используйте адаптер google в Flysystem.
  3. Задача 3: Сгенерируйте превью для загруженного изображения и сохраните его в облако.
    Пример: После загрузки изображения вызовите generateThumbnail() и сохраните результат в S3.

Сегодня вы освоили работу с файлами в Symfony, от загрузки через формы до хранения в облаке. Это важный навык для создания современных веб-приложений. Если что-то осталось непонятным, пишите вопросы в комментариях.

Хотите продолжить обучение? Переходите к полному курсу по Symfony для начинающих. Жду вас на следующем уроке.

Поделиться статьей:
Поддержать автора блога

Поддержка автора осуществляется с помощью специальной формы ниже, предоставленной сервисом «ЮMoney». Все платёжные операции выполняются на защищённой странице сервиса, что обеспечивает их корректность и полную безопасность.

Персональные рекомендации
Оставить комментарий