How to manually handle file downloads with symfony2?

Since I have a custom jQuery plugin for transferring files to my symfony2 webapp, I am looking for ways to handle this download in the controller.

The standard (non-ajax) file upload that I currently have (and which works fine for synchronous calls) looks like this:

Excerpt for controller

... $entity = new Image(); $request = $this->getRequest(); $form = $this->createForm(new ImageType($createAction), $entity); $form->bind($request); // <-- Find a way to make this connection manually?! //check that a file was chosen $fileExists = isset($entity->file); if ( ($form->isValid()) && ($fileExists) ) { $em = $this->getDoctrine()->getManager(); $em->persist($entity); $em->flush(); } ... 

Type of form : the form just takes the file and name:

 class ImageType extends AbstractType { ... public function buildForm(FormBuilderInterface $builder, array $options) { $createAction = $this->createAction; if ($createAction) { $builder ->add('file') ; } $builder ->add('name', 'text', array('label' => 'Namn')) ; } ... } 

As I understand it (or, in other words, DO NOT VIEW), the system for downloading files with symfony2 and the doctrine there is quite a lot of magic passing under the hood during this call

 $form->bind($request); 

For example, if I skip this bind () and instead try to create an Image object manually, like this ...

  $request = $this->getRequest(); $parent = $request->request->get('parent'); $file = $request->request->get('file1'); $name = $request->request->get('name'); $entity->setName( $name ); $entity->setFile( $file ); $entity->setFolder( null ); 

... I find that it doesn't even have setFile (), so it will take care of something else. Here is what the Image Object is :

 namespace BizTV\MediaManagementBundle\Entity; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Constraints as Assert; /** * BizTV\MediaManagementBundle\Entity\Image * * @ORM\Table(name="image") * @ORM\Entity * @ORM\HasLifecycleCallbacks */ class Image { /** * @var integer $id * * @ORM\Column(name="id", type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="AUTO") */ private $id; /** * @var string $name * * @ORM\Column(name="name", type="string", length=255) * @Assert\NotBlank(message = "Bilden mΓ₯ste ha ett namn") */ private $name; /** * @var integer $width * * @ORM\Column(name="width", type="integer") */ private $width; /** * @var integer $height * * @ORM\Column(name="height", type="integer") */ private $height; /** * @ORM\Column(type="string", length=255, nullable=true) */ private $path; //The deleteRequested variable is to flag that an image has been deleted by user. //Due to slideshow issues we can however not delete the image right away, we can't risk to remove it from the //cache manifest before the slideshow round is up. /** * @var time $deleteRequested * * @ORM\Column(name="delete_requested", type="datetime", nullable=true) */ private $deleteRequested; /** * @var object BizTV\BackendBundle\Entity\company * * @ORM\ManyToOne(targetEntity="BizTV\BackendBundle\Entity\company") * @ORM\JoinColumn(name="company", referencedColumnName="id", nullable=false) */ protected $company; /** * @var object BizTV\MediaManagementBundle\Entity\Folder * * @ORM\ManyToOne(targetEntity="BizTV\MediaManagementBundle\Entity\Folder") * @ORM\JoinColumn(name="folder", referencedColumnName="id", nullable=true) */ protected $folder; /** * @Assert\File(maxSize="12000000") */ public $file; /** * @ORM\OneToOne(targetEntity="BizTV\MediaManagementBundle\Entity\QrImage", mappedBy="image") */ protected $qr; /** * @ORM\PrePersist() * @ORM\PreUpdate() */ public function preUpload() { if (null !== $this->file) { // do whatever you want to generate a unique name $this->path = sha1(uniqid(mt_rand(), true)).'.'.$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); } } 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/images/'.$this->getCompany()->getId(); } /** * Get id * * @return integer */ public function getId() { return $this->id; } /** * Set name * * @param string $name */ public function setName($name) { $this->name = $name; } /** * Get name * * @return string */ public function getName() { return $this->name; } /** * Set width * * @param integer $width */ public function setWidth($width) { $this->width = $width; } /** * Get width * * @return integer */ public function getWidth() { return $this->width; } /** * Set height * * @param integer $height */ public function setHeight($height) { $this->height = $height; } /** * Get height * * @return integer */ public function getHeight() { return $this->height; } /** * Set path * * @param string $path */ public function setPath($path) { $this->path = $path; } /** * Get path * * @return string */ public function getPath() { return $this->path; } /** * Set company * * @param BizTV\BackendBundle\Entity\company $company */ public function setCompany(\BizTV\BackendBundle\Entity\company $company) { $this->company = $company; } /** * Get company * * @return BizTV\BackendBundle\Entity\company */ public function getCompany() { return $this->company; } /** * Set folder * * @param BizTV\MediaManagementBundle\Entity\Folder $folder */ public function setFolder(\BizTV\MediaManagementBundle\Entity\Folder $folder = NULL) { $this->folder = $folder; } /** * Get folder * * @return BizTV\MediaManagementBundle\Entity\Folder */ public function getFolder() { return $this->folder; } /** * Set qr * * @param BizTV\MediaManagementBundle\Entity\QrImage $qr */ public function setQr(\BizTV\MediaManagementBundle\Entity\QrImage $qr = null) { $this->qr = $qr; } /** * Get qr * * @return BizTV\MediaManagementBundle\Entity\QrImage */ public function getQr() { return $this->qr; } /** * Set deleteRequested * * @param date $deleteRequested */ public function setDeleteRequested($deleteRequested = null) { $this->deleteRequested = $deleteRequested; } /** * Get deleteRequested * * @return date */ public function getDeleteRequested() { return $this->deleteRequested; } } 
+7
jquery php forms file-upload symfony
source share
3 answers

I found what I was looking for. To access files uploaded to symfony from the controller, you just need to do this:

  $request = $this->getRequest(); $file = $request->files->get('file1'); //file1 being the name of my form field for the file /* if your entity is set up like mine - like they teach you in the symfony2 cookbook * file is actually a public property so you can just set it like this **/ $entity->file = $file; //and here how you get the original name of that file $entity->setName( $file->getClientOriginalName() ); 
+6
source share

First of all, if you want to get an entity with your file after the submit / bind / handleRequest or smth else form, you need to provide the data_class option in the form configuration method ( setDefaultOptions , etc.). And only after that your form will begin to return the necessary object after submitting.

+4
source share

1) First create your entity:

 namespace XXX; use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Constraints as Assert; /** * @ORM\Table() * @ORM\Entity */ class Article { /** * @var integer $id * * @ORM\Column(name="id", type="integer") * @ORM\Id * @ORM\GeneratedValue(strategy="AUTO") */ private $id; /** * @var string $image * @Assert\File( maxSize = "1024k", mimeTypesMessage = "Please upload a valid Image") * @ORM\Column(name="image", type="string", length=255) */ private $image; /** * Get id * * @return integer */ public function getId() { return $this->id; } /** * Set image * * @param string $image */ public function setImage($image) { $this->image = $image; } /** * Get image * * @return string */ public function getImage() { return $this->image; } } 

2) create a form: so we will create a simple form type for this article object to fit into other forms: ArticleType.php

 use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilder; class ArticleType extends AbstractType { public function buildForm(FormBuilder $builder, array $options) { $builder ->add('image') ->add('...') ; } public function getName() { return 'xxx_articletype'; } } 

3) Create a controller: the controller below shows you how to manage the whole process: ArticleController.php:

 use Symfony\Bundle\FrameworkBundle\Controller\Controller; /** * Article controller. * */ class ArticleController extends Controller { /** * Finds and displays a Article entity. * */ public function showAction($id) { $em = $this->getDoctrine()->getEntityManager(); $entity = $em->getRepository('XXXBundle:Article')->find($id); if (!$entity) { throw $this->createNotFoundException('Unable to find Article entity.'); } return $this->render('XXXBundle:Article:show.html.twig', array( 'entity' => $entity, )); } /** * Displays a form to create a new Article entity. * */ public function newAction() { $entity = new Article(); //$entity = $em->getRepository('CliniqueGynecoBundle:Article'); $form = $this->createForm(new ArticleType(), $entity); return $this->render('XXXBundle:Article:new.html.twig', array( 'entity' => $entity, 'form' => $form->createView() )); } /** * Creates a new Article entity. * */ public function createAction() { $entity = new Article(); $request = $this->getRequest(); $form = $this->createForm(new ArticleType(), $entity); $form->bindRequest($request); if ($form->isValid()) { $em = $this->getDoctrine()->getEntityManager(); $em->persist($entity); $em->flush(); return $this->redirect($this->generateUrl('article_show', array('id' => $entity->getId()))); } return $this->render('XXXBundle:Article:new.html.twig', array( 'entity' => $entity, 'form' => $form->createView() )); } private function createDeleteForm($id) { return $this->createFormBuilder(array('id' => $id)) ->add('id', 'hidden') ->getForm() ; } } 

4) layout for upload form: new.html.twig

 <form action="{{ path('basearticle_create') }}" method="post" {{ form_enctype(form) }}> {{ form_widget(form) }} <p> <button class="btn btn-primary" type="submit">Create</button> </p> </form> 

5) Display layout: show.html.twig

 <table> <tr> <td align="center" valign="top"><img src="{{ asset('upload/' ~ entity.id ~'/' ~ entity.image)}}" alt="" height="525" width="666" /></td> </tr> </table> 

6) Use the "Lifecycle Callbacks", connecting the object to the "Lifecycle Callbacks": "@ORM \ HasLifecycleCallbacks"

 /** * * @ORM\Table() * @ORM\HasLifecycleCallbacks * @ORM\Entity */ class Article { .... 

7) Added file upload methods:

 class Article { .................................... public function getFullImagePath() { return null === $this->image ? null : $this->getUploadRootDir(). $this->image; } protected function getUploadRootDir() { // the absolute directory path where uploaded documents should be saved return $this->getTmpUploadRootDir().$this->getId()."/"; } protected function getTmpUploadRootDir() { // the absolute directory path where uploaded documents should be saved return __DIR__ . '/../../../../web/upload/'; } /** * @ORM\PrePersist() * @ORM\PreUpdate() */ public function uploadImage() { // the file property can be empty if the field is not required if (null === $this->image) { return; } if(!$this->id){ $this->image->move($this->getTmpUploadRootDir(), $this->image->getClientOriginalName()); }else{ $this->image->move($this->getUploadRootDir(), $this->image->getClientOriginalName()); } $this->setImage($this->image->getClientOriginalName()); } /** * @ORM\PostPersist() */ public function moveImage() { if (null === $this->image) { return; } if(!is_dir($this->getUploadRootDir())){ mkdir($this->getUploadRootDir()); } copy($this->getTmpUploadRootDir().$this->image, $this->getFullImagePath()); unlink($this->getTmpUploadRootDir().$this->image); } /** * @ORM\PreRemove() */ public function removeImage() { unlink($this->getFullImagePath()); rmdir($this->getUploadRootDir()); } 
+3
source share

All Articles