Download Symfony2 File

I am still learning Symfony2 and don’t understand how to download the file.

Don’t worry, I already checked the documentation . This is really good, but my problem is not explained in any lesson.

I am looking for a guide to downloading a file using Symfony2, but with everything everyone needs (for example, limiting the extension, renaming the file based on id, etc., saving the path in db, etc.) ...)

I found good lessons, tried to mix them, but without success. Every time another problem arises: reloading files on each form submission (even if the file field is empty), guessExtension cannot be used, the tmp path stored in the database, and not the correct path, the file is not moved, it was impossible to use the identifier in renaming, because the identifier is included automatically and therefore has not yet been generated).

So, I will put the "standard" entity, say: Photo.php

/** * Photo * * @ORM\Table(name="photo") * @ORM\Entity * @ORM\HasLifecycleCallbacks */ class Photo { // Annotation for the id and auto increment etc private $id; /** * @var string * @Assert\File( maxSize = "3072k", mimeTypesMessage = "Please upload a valid Image") * @ORM\Column(name="image", type="string", length=245, nullable=false) */ private $image private $title private $description // all the function get, set for the 4 previous variables } 

and controller:

 public function addPhotoAction() { $add_photo = new Photo; $formBuilderPhoto = $this->createFormBuilder($add_photo); $formBuilderPhoto ->add('title','text',array('label' => 'Title of the photo', 'required' => true)) ->add('image','file', array('required' => true, 'data_class' => null)) ->add('description','textarea',array('label' => 'Description of your photo', 'required' => false)) ; $form_photo = $formBuilderPhoto->getForm(); if ($request->getMethod() == 'POST') { $form_photo->bind($request); if ($form_photo->isValid()) { // ... } } return $this->render('MyBundle:frontend:photo.html.twig', array('form_photo' => $form_photo->createView()) ); } 

Do you know what an “important” function to add is to upload a photo and rename it?

How to check the extension to see if download is possible?

What is your real way to do this with Symfony2? I know that there are many Bundle that do all this for you, but I want to learn how to do it and understand the process.

What is the “classic” way to implement a file upload and rename form using Symfony2?

+51
file upload symfony doctrine2 formbuilder
Jul 30 '13 at 15:31
source share
3 answers

Do you know what an “important” function to add is to upload a photo and rename it?

See the official documentation on how to do this. There are good working examples for simple file uploads. Also check out the doctrine documentation for lifecycle callbacks .

How to check the extension to see if download is possible?

Each browser has an HTML form check. See this question for the HTML attribute accept="" in input . Also in Symfony2, you can specify the MIME type of the downloaded file using this annotation:

 /** * @Assert\File( * maxSize = "1024k", * mimeTypes = {"application/pdf", "application/x-pdf"}, * mimeTypesMessage = "Please upload a valid PDF" * ) */ 

Even if you do not want to use any bundles, I should recommend you KnpDoctrineBehavioursBundle , which makes downloading files easier.




Step by step:

Since you already read the documentation, I will give you a step-by-step code example.

First of all, you need an entity. Let me call it Image :

 /** * Class Image * * @ORM\Entity() * @ORM\HasLifecycleCallbacks */ class Image extends BaseEntity { 

Note the annotation @ORM\HasLifecycleCallbacks . This is very important, and you need it later. We create all the main fields, such as ID and what not. We also need a field to store the file path in:

  /** * Image path * * @var string * * @ORM\Column(type="text", length=255, nullable=false) */ protected $path; 

And one for the image itself. Here we also define validation for images. In my example, this should be 5M large and one of the defined mimeTypes . It should be clear. Otherwise, official documents help, as always.

  /** * Image file * * @var File * * @Assert\File( * maxSize = "5M", * mimeTypes = {"image/jpeg", "image/gif", "image/png", "image/tiff"}, * maxSizeMessage = "The maxmimum allowed file size is 5MB.", * mimeTypesMessage = "Only the filetypes image are allowed." * ) */ protected $file; 

Add all Getters & Setters and update the database schema with this command:

 php app/console doctrine:schema:update --force 

Next we need lifecycles . These are methods in Entity that are called on certain events. For example, the annotation @ORM\PreUpdate() before a method indicates that this method is called immediately before updating the entity.

 /** * Called before saving the entity * * @ORM\PrePersist() * @ORM\PreUpdate() */ public function preUpload() { if (null !== $this->file) { // do whatever you want to generate a unique name $filename = sha1(uniqid(mt_rand(), true)); $this->path = $filename.'.'.$this->file->guessExtension(); } } 

Before an object is saved or updated, this method is called. You can use it, for example, generate a unique file name.

 /** * Called before entity removal * * @ORM\PreRemove() */ public function removeUpload() { if ($file = $this->getAbsolutePath()) { unlink($file); } } 

Called before an object is deleted. This gives you time to delete an image from your folders or register a message if you want.

 /** * Called after entity persistence * * @ORM\PostPersist() * @ORM\PostUpdate() */ public function upload() { // The file property can be empty if the field is not required if (null === $this->file) { return; } // Use the original file name here but you should // sanitize it at least to avoid any security issues // move takes the target directory and then the // target filename to move to $this->file->move( $this->getUploadRootDir(), $this->path ); // Set the path property to the filename where you've saved the file //$this->path = $this->file->getClientOriginalName(); // Clean up the file property as you won't need it anymore $this->file = null; } 

This is an important part where your file is actually moved to the correct directory. Please note that I used some additional methods. You can get them from official white papers .

The next thing you need is a form. The form class itself is very simple. Just make sure you set the default data_class as follows:

 public function setDefaultOptions(OptionsResolverInterface $resolver) { $resolver->setDefaults( array( 'data_class' => 'FSchubert\SiyabongaBundle\Entity\Image', ) ); } 

A file upload field can be created very easily in the buildForm() method:

 $builder->add('file', 'file'); 

The methods for your Controller bit long for just pasting them here, and IMHO is not part of the answer to your question. There are many examples for writing the right Controller Action for your purpose.




More things you should keep in mind:

  • You need to grant your write permissions to the app for the files to which you upload the files. Although it seems obvious, it can be annoying if you have several servers on which you are running the application.
  • There is Image Constraint for your object. You can find it here . But since you were talking about downloading a file , I used File Constraint .
  • As I mentioned at the beginning of this post, there are many Bundles that handle all of these things for you. Check them out if you need an easy life.

Edit:

  • Changed from DoctrineExtensionsBundle to DoctrineBehaviours , since development on the old one was stopped in favor of the DoctrineBehaviours package.
+107
Jul 30 '13 at 19:41
source share

I recommend you use vlabs media bundle .

+13
Jul 31 '13 at 2:43
source share

VichUploaderBundle is also easy to use for downloading files:

https://github.com/dustin10/VichUploaderBundle

+6
Feb 05 '15 at 10:25
source share



All Articles