使用 VichUploaderBundle 通过 API 上传文件

Using VichUploaderBundle to upload a file through an API

所以,我需要的是基本的文件上传。我拥有的是 Symfony 4 和 VichUploaderBundle,它们完全按照描述集成 https://symfony.com/doc/current/bundles/EasyAdminBundle/integration/vichuploaderbundle.html

实体标记为@Vich\Uploadable,字段定义正确:

/**
 * @Vich\UploadableField(mapping="images", fileNameProperty="fileName")
 * @var File
 */
private $file;

/**
 * @ORM\Column(type="string", length=255)
 */
private $fileName;

这是我的类型:

class MyType extends AbstractType
{
    public function buildForm(FormBuilderInterface $builder, array $options)
    {
        $builder
            ->add('name', TextType::class)
            ->add('file', VichImageType::class, ['allow_file_upload' => true])
        ;
    }

    public function configureOptions(OptionsResolver $resolver)
    {
        $resolver->setDefaults([
            'data_class' => My::class,
            'allow_extra_fields' => false,
            'http_method' => 'POST'
        ]);

        $resolver->setRequired('http_method');
    }
}

我的控制器中有:

$form = $this->createForm(MyType::class, null);
    $form->submit(array_merge($request->request->all(), $request->files->all()));

    if ($form->isSubmitted() && $form->isValid()) {
        /** @var $my */
        $my = $form->getData();
        $em = $this->getDoctrine()->getManager();
        $em->persist($my);
        $em->flush();

        return $this->json($my);
    }

结果是 TransformationException:

Compound forms expect an array or NULL on submission.

我已经用 xDebug 调试了整个过程——它第一次成功提交了 name 字段,甚至 file 字段。但是随后,出于某种原因,它认为它是一种复合形式并尝试再次提交它 - 这显然会导致转换异常 https://github.com/symfony/form/blob/master/Form.php#L571

而且,当我尝试设置 'compound' => false 时,它根本不提交文件字段。

这可能是什么问题?我在文档中看到,为了将它与 EasyAdmin 一起使用,只需指定字段名称和类型 'vich_image' 就足够了,为什么它在 EasyAdmin 之外不起作用?顺便说一句,你可能会注意到我添加了额外的参数 'allow_file_upload' => true 因为没有它就不会提交 https://github.com/symfony/form/blob/master/Form.php#L534

所以,一些进一步的研究使我得到了这个答案https://github.com/dustin10/VichUploaderBundle/issues/769#issuecomment-477173161

解决方案是像这样提交表单:

$form->submit(array_merge(
    $request->request->all(),
    ['file' => $request->files->all()]
));