ragnar_ok
@ragnar_ok

Symfony Form & FOSRESTBundle: Как загрузить файл?

Разрабатываю REST API с использованием Symfony4, FOSRestBundle и Symfony/Serializer.
Отправляю POST-запрос через Postman (файл). Выводит ошибку валидации 'Please, upload the file' (поле file пустое) при submit.
Я создал другую форму, используя не FOSRestBundle, а Controller. То есть я вывел html-форму на странице ($this->render()). Заменил $form->submit($request->request->all()) на $form->handleRequest($request), остальное оставил как есть. Файл загружается.
То есть дело в handleRequest? Но как его использовать с json?

App\Entity\User:

/**
             * @ORM\Entity(repositoryClass="App\Repository\UserRepository")
             */
            class User
            {
                // ...
            
                /**
                 * @ORM\Column(type="string", length=255)
                 * @Assert\NotBlank(message="Please, upload the file.")
                 * @Assert\File(maxSize="50000k", mimeTypes={ "application/pdf", "application/vnd.ms-powerpoint" })
                 */
                private $file;
            
                public function getFile()
                {
                    return $this->file;
                }
            
                public function setFile($file): self
                {
                    $this->file = $file;
            
                    return $this;
                }
        
                // ...
            }


App\Form\UserType

class UserType extends AbstractType
            {
                public function buildForm(FormBuilderInterface $builder, array $options)
                {
                    $builder->add('file', FileType::class);
                }
            
                public function configureOptions(OptionsResolver $resolver)
                {
                    $resolver->setDefaults([
                        'data_class' => User::class,
                        'csrf_protection' => false
                    ]);
                }
            }


App\Controller\UserController

class UserController extends FOSRestController
        {
            public function postUserAction(Request $request)
            {
                $user = new User();
            
                $form = $this->createForm(UserType::class, $user);
                $data = json_decode($request->request->all(), true);
                $form->submit($data);

                if ($form->isSubmitted() && $form->isValid()) {
                    $file = $user->getFile();
                    $fileName = $this->generateUniqueFileName().'.'.$file->guessExtension();
                    $file->move(
                        $this->getParameter('file_directory'),
                        $fileName
                    );
                    $user->setFile($fileName);
            
                    $em = $this->getDoctrine()->getManager();
                    $em->persist($user);
                    $em->flush();
                    return $this->handleView($this->view(['status' => 'created'], Response::HTTP_CREATED, ['Access-Control-Allow-Origin' => '*']));
                }
                return $this->handleView($this->view($form->getErrors(true, false)));
            }
        }
  • Вопрос задан
  • 710 просмотров
Решения вопроса 1
BoShurik
@BoShurik Куратор тега Symfony
Symfony developer
Вы забыли добавить данные из files. Можно посмотреть как это сделано в HttpFoundationRequestHandler
$params = $request->request->all();
$files = $request->files->all();

$data = array_replace_recursive($params, $files);

$form->submit($data);


Если вы хотите посылать json + файл, то файл придется передавать в base64: https://stackoverflow.com/questions/4083702/postin...
либо немного подкорректировать структуру запроса (json передавать в одном поле, а файлы - в другом):
https://stackoverflow.com/a/13076550/1247234

В первом случае использование формы под вопросом (придется какой-то кастомный DataTransformer изобретать), а вот во втором - вполне себе можно пробросить соответствующие данные в submit как показано выше

Но все-таки лучше формы не использовать, а делать напрямую через serializer/validator: Как правильно фильтровать и мапить данные при реализации API на Symfony4? , т.к. основная фишка форм - это их вывод, который вы не используете
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
mad_maximus
@mad_maximus
Не используйте формы.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы