Problems With Multiple File Upload In Symfony2
doctrine-orm, file-upload, php, symfony, symfony-forms
Solution
This is a known issue as referenced on GitHub.
As they say, you should append `[]` to the `full_name` attribute in your template :
{{ form_widget(images_form.file, { 'full_name': images_form.file.get('full_name') ~ '[]' }) }}
Problem
I am making a Symfony2 application which needs to have a multiple image upload option. I have made the single file upload using the cookbook entry: How to handle File Uploads with Doctrine which works fine. I have implemented the lifecyclecallbacks for uploading and removing. Now I need to turn this into a multiple upload system. I have read a few answers from Stack Overflow as well, but nothing seems to work. Stack Overflow Question: - Multiple file upload with Symfony2 - multiple file upload symfony 2 I have the following code at the moment: File Entity: ``` <?php namespace Webmuch\ProductBundle\Entity; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Constraints as Assert; use Symfony\Component\HttpFoundation\File\UploadedFile; /** * @ORM\Entity * @ORM\HasLifecycleCallbacks */ class File { /** * @ORM\Id * @ORM\Column(type="integer") * @ORM\GeneratedValue(strategy="AUTO") */ public $id; /** * @ORM\Column(type="string", length=255, nullable=true) */ public $path; /** * @Assert\File(maxSize="6000000") */ public $file = array(); public function __construct() { } /** * Get id * * @return integer */ public function getId() { return $this->id; } /** * Set path * * @param string $path */ public function setPath($path) { $this->path = $path; } /** * Get path * * @return string */ public function getPath() { return $this->path; } public function getAbsolutePath() { return null === $this->path ? null : $this->getUploadRootDir().'/'.$this->path; } public function getWebPath() { return null === $this->path ? null : $this->getUploadDir().'/'.$this->path; } protected function getUploadRootDir() { // the absolute directory path where uploaded documents should be saved return __DIR__.'/../../../../web/'.$this->getUploadDir(); } protected function getUploadDir() { // get rid of the __DIR__ so it doesn't screw when displaying uploaded doc/image in the view. return 'uploads'; } /** * @ORM\PrePersist() * @ORM\PreUpdate() */ public function preUpload() { if (null !== $this->file) { // do whatever you want to generate a unique name $this->path[] = uniqid().'.'.$this->file->guessExtension(); } } /** * @ORM\PostPersist() * @ORM\PostUpdate() */ public function upload() { if (null === $this->file) { return; } // if there is an error when moving the file, an exception will // be automatically thrown by move(). This will properly prevent // the entity from being persisted to the database on error $this->file->move($this->getUploadRootDir(), $this->path); unset($this->file); } /** * @ORM\PostRemove() */ public function removeUpload() { if ($file = $this->getAbsolutePath()) { unlink($file); } } } ``` FileController: ``` <?php namespace Webmuch\ProductBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Method; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template; use Webmuch\ProductBundle\Entity\File; /** * File controller. * * @Route("/files") */ class FileController extends Controller { /** * Lists all File entities. * * @Route("/", name="file_upload") * @Template() */ public function uploadAction() { $file = new File(); $form = $this->createFormBuilder($file) ->add('file','file',array( "attr" => array( "accept" => "image/*", "multiple" => "multiple", ) )) ->getForm() ; if ($this->getRequest()->getMethod() === 'POST') { $form->bindRequest($this->getRequest()); $em = $this->getDoctrine()->getEntityManager(); $em->persist($file); $em->flush(); $this->redirect($this->generateUrl('file_upload')); } return array('form' => $form->createView()); } } ``` and the upload.html.twig: ``` {% extends '::base.html.twig' %} {% block body %} <h1>Upload File</h1> <form action="#" method="post" {{ form_enctype(form) }}> {{ form_widget(form.file) }} <input type="submit" value="Upload" /> </form> {% endblock %} ``` I don't know what to do to make this work as a multiple file upload system. I have kept the comments as they are from the tutorials I have followed so I can remember what is doing what. UPDATE: New Form Code: ``` $images_form = $this->createFormBuilder($file) ->add('file', 'file', array( "attr" => array( "multiple" => "multiple", "name" => "files[]", ) )) ->getForm() ; ``` New Form Twig Code: ``` <form action="{{ path('file_upload') }}" method="post" {{ form_enctype(images_form) }}> {{ form_label(images_form.file) }} {{ form_errors(images_form.file) }} {{ form_widget(images_form.file, { 'attr': {'name': 'files[]'} }) }} {{ form_rest(images_form) }} <input type="submit" /> </form> ```