R
R
ragnar_ok2019-07-08 18:22:29
symfony
ragnar_ok, 2019-07-08 18:22:29

Symfony Form & FOSRESTBundle: How to upload a file?

I am developing a REST API using Symfony4, FOSRestBundle and Symfony/Serializer.
I send a POST request via Postman (file). Throws validation error 'Please, upload the file' (field fileempty) on submit.
I created another form using Controller instead of FOSRestBundle. That is, I displayed the html form on the page ( $this->render()). Replaced $form->submit($request->request->all())with $form->handleRequest($request), left the rest as is. The file is being loaded.
That is the case in handleRequest? But how to use it with 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)));
            }
        }

Answer the question

In order to leave comments, you need to log in

2 answer(s)
B
BoShurik, 2019-07-08
@ragnar_ok

You forgot to add data from files. You can see how it's done in HttpFoundationRequestHandler

$params = $request->request->all();
$files = $request->files->all();

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

$form->submit($data);

If you want to send a json + file, then you will have to send the file in base64: https://stackoverflow.com/questions/4083702/postin...
or slightly adjust the request structure (pass json in one field, and files in another):
https://stackoverflow.com/a/13076550/1247234
In the first case, the use of the form is questionable (you will have to invent some kind of custom DataTransformer), but in the second case, it’s quite possible to pass the corresponding data in submitas shown above.
But still, it’s better do not use forms, but do it directly through serializer/validator: How to filter and map data correctly when implementing API on Symfony4? , because the main feature of forms is their output, which you do not use

K
kafkiansky, 2019-07-08
@mad_maximus

Don't use forms.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question