Carga del archivo Symfony2 paso a paso

Todavía estoy aprendiendo Symfony2 y no entiendo cómo cargar un archivo.

No te preocupes, ya he revisado la documentación . Es realmente bueno, pero mi problema no se explica en ningún tutorial.

Estoy buscando orientación sobre cómo cargar un archivo con Symfony2 pero con todo lo que todo el mundo necesita (como la restricción de la extensión, cambiar el nombre del archivo en función del ID y esas cosas, almacenar la ruta en la base de datos, etc.)

Encontré buenos tutoriales, intenté mezclarlos pero sin éxito. Cada vez que aparece un problema diferente: volver a subir archivos en cada envío del formulario (incluso si el campo del archivo está vacío), guessExtension impossible to used, tmp path almacenado en la base de datos en lugar de la ruta correcta, archivo no movido, imposible usó la identificación en el renombrado porque la identificación está en autoincremento y aún no se ha generado).

Entonces, pondré una entidad ‘estándar’, digamos: 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 } 

y el controlador:

 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()) ); } 

¿Sabe ahora cuál es la función “importante” que debe agregar para poder cargar la foto y cambiarle el nombre?

¿Cómo verifica la extensión para ver si la carga es posible?

¿Cuál es tu forma real de hacer tal cosa con Symfony2? Sé que hay muchos Bundle que hacen todo eso por ti, pero quiero aprender a hacerlo y entender el proceso.

¿Cuál es la forma “clásica” de implementar un formulario de carga de archivos y cambiar el nombre de la función con Symfony2?

¿Sabe ahora cuál es la función “importante” que debe agregar para poder cargar la foto y cambiarle el nombre?

Vea la documentación oficial sobre cómo hacer esto. Hay buenos ejemplos de trabajo para una simple carga de archivos. También verifique la documentación de la doctrine para las devoluciones de llamadas del ciclo de vida .

¿Cómo verifica la extensión para ver si la carga es posible?

Hay alguna validación de formulario HTML en cada navegador. Consulte esta pregunta para el atributo HTML accept="" en input elementos de input . También en Symfony2 puede especificar el tipo MIME de un archivo cargado utilizando esta anotación:

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

A pesar de que no quería utilizar ningún paquete, tendré que recomendarle KnpDoctrineBehavioursBundle, que facilita la carga de archivos.


Paso a paso:

Debido a que ya leyó la documentación, le daré un ejemplo de código paso a paso.

Primero que nada, necesitas una entidad. Vamos a llamarlo Image :

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

Tenga en cuenta la anotación @ORM\HasLifecycleCallbacks . Es muy importante y lo necesitas más tarde. Creamos todos los campos básicos como ID y lo que no. También necesitamos un campo para almacenar la ruta del archivo en:

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

Y uno para la Imagen misma. Aquí también definimos la Validación para las imágenes. En mi ejemplo, tiene que ser 5M grande y uno de los mimeTypes definidos. Debe ser autoexplicativo. De lo contrario, los documentos oficiales ayudan como siempre.

  /** * 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; 

Agregue todos los Getters & Setters y actualice su esquema de base de datos con este comando:

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

Luego necesitamos los ciclos de vida . Son métodos en la Entity que son llamados en ciertos eventos. Por ejemplo, la @ORM\PreUpdate() antes de un método indica que este método se está llamando justo antes de que la entidad se actualice.

 /** * 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(); } } 

Antes de que la entidad sea almacenada o actualizada, se llama a este método. Puede usarlo para, por ejemplo, generar un nombre de archivo único.

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

Invocado antes de que la entidad sea eliminada. Esto le da tiempo para borrar la imagen de sus carpetas o registrar un mensaje si lo desea.

 /** * 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; } 

Esta es la parte importante donde su archivo se mueve realmente al directorio correcto. Tenga en cuenta que he usado algunos métodos adicionales. Todos pueden obtenerlos de los documentos oficiales .

Lo siguiente que necesitas es un formulario. La clase de formulario en sí es muy simple. Solo asegúrate de configurar la data_class predeterminada de esta manera:

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

Un campo de carga de archivos se puede crear muy fácilmente en el método buildForm() :

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

Los métodos para su Controller son un poco largos para simplemente pegarlos aquí y en mi humilde opinión no es parte de responder su pregunta. Existen innumerables ejemplos para escribir una Controller Action adecuada para su propósito.


Más cosas que debes tener en cuenta:

  • Debes otorgar permisos a tu app escribir en las carpetas donde cargas los archivos. Aunque parece obvio, puede ser molesto si tienes varios servidores en los que ejecutas la aplicación.
  • También existe una Image Constraint para su entidad. Puedes encontrarlo aquí . Pero como hablaste de una carga de archivos , usé la File Constraint lugar.
  • Como mencioné en la parte superior de esta publicación, hay muchos paquetes que manejan todo esto por usted. Échales un vistazo si quieres una vida fácil.

Editar:

  • Se cambió de DoctrineExtensionsBundle a DoctrineBehaviours porque el desarrollo en el anterior se detuvo en favor del paquete DoctrineBehaviours .

Te recomiendo que uses el paquete de medios vlabs .

El VichUploaderBundle también es fácil de usar para cargar archivos:

https://github.com/dustin10/VichUploaderBundle