symfony 4, 5 Загрузка файлов - пример формы (Type, AbstractType) и контроллера

Форма (список нужных mime-типов получен через MIME::getAllbyExtentions() из rusphp):

namespace App\Form;

use App\Entity\Image;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
use Symfony\Component\Form\Extension\Core\Type\FileType;
use Symfony\Component\Validator\Constraints\File;

use ItForFree\rusphp\File\MIME;

class ImageType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        
        $builder
            ->add('title')
            ->add('description')
            ->add('image_file', FileType::class, [
                'label' => 'Image',

                // false означает, что нет  ассоциации с каким-то из полей модели (и БД)
                'mapped' => false,

                'required' => true,

                // поля, не ассоцированные с сущность (энтити), не могут быть валидированы
                // с помощью аннотаций этой сущности, 
                // но можно использовать специальный класс ограничений:
                'constraints' => [
                    new File([
                        'maxSize' => '1024k',
                        'mimeTypes' => MIME::getAllbyExtentions(['png', 'jpg']),
                        'mimeTypesMessage' => 'Поддерживается только загрузка изображений!',
                    ])
                ],
            ])
            ->add('save', SubmitType::class)
        ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => Image::class,
        ]);
    }
}

Код метода контроллера, использующего эту форму:

/**
 * 
 * @IsGranted("ROLE_ADMIN")
 * @Route("/image/create", name="create_image")
 */
public function createImage(Request $request)
{
	$Image = new Image();
	$imageForm = $this->createForm(ImageType::class, $Image);

	$imageForm->handleRequest($request);

	if ($imageForm->isSubmitted() && $imageForm->isValid()) {

		$Image = $imageForm->getData();

		$imageFile = $imageForm['image_file']->getData();
		if ($imageFile) {
			$originalFilename = pathinfo($imageFile->getClientOriginalName(), PATHINFO_FILENAME);

			// чтобы безопасно использовать имя файла как часть URL преобразуем его
			$safeFilename = transliterator_transliterate('Any-Latin; Latin-ASCII; [^A-Za-z0-9_] remove; Lower()', $originalFilename);
			$newFilename = $safeFilename . '-' . uniqid() . '.' . $imageFile->guessExtension();

			// перемещаем файл в нужную директорию             
			$currentDatePath = (new \DateTime('now'))->format('Y/m/d');
			$folderPath = Path::concat([$this->getParameter('images_directory'), $currentDatePath]);

			try {
				$imageFile->move(
					$folderPath,
					$newFilename
				);
			} catch (FileException $e) {
				// обрабатываем исключение на случай если что-то пошло не так
			}

			//
			$Image->setFilePath(Path::concat([$currentDatePath, $newFilename]));
		}

		$entityManager = $this->entityManager;
		$entityManager->persist($Image);
		$entityManager->flush();

		return $this->redirectToRoute('image-list');
	}

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

Задать параметр - путь к базовой директории загрузки можно так (/config/services.yaml):

parameters:
    images_directory: '%kernel.project_dir%/public/uploads/images'

Документация: https://symfony.com/doc/current/controll...

vedro-compota's picture

MIME::getAllbyExtentions() позволяет удобно получить массив mime-типов по списку расширений файлов

_____________
матфак вгу и остальная классика =)