2012-05-04 2 views
13

Je crée une application Symfony2 qui doit avoir une option de téléchargement d'images multiples. J'ai fait le téléchargement de fichier unique en utilisant l'entrée de livre de cuisine: How to handle File Uploads with Doctrine qui fonctionne bien. J'ai mis en œuvre le lifecyclecallbacks pour le téléchargement et la suppression. Maintenant, je dois transformer cela en un système de téléchargement multiple. J'ai aussi lu quelques réponses de Stack Overflow, mais rien ne semble fonctionner.Problèmes de téléchargement de fichiers multiples dans Symfony2

Stack Overflow Question:

  1. Multiple file upload with Symfony2
  2. multiple file upload symfony 2

je le code suivant au moment:

fichier Entité:

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

et 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 %} 

Je ne sais pas quoi faire pour faire ce travail comme un système de téléchargement de fichiers multiples . J'ai gardé les commentaires tels qu'ils sont tirés des tutoriels que j'ai suivis pour que je puisse me souvenir de ce qui fait quoi.

MISE À JOUR:

Nouveau Code Forme:

$images_form = $this->createFormBuilder($file) 
    ->add('file', 'file', array(
      "attr" => array(
       "multiple" => "multiple", 
       "name" => "files[]", 
      ) 
     )) 
    ->getForm() 
; 

Nouveau formulaire 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> 
+0

Qu'est-ce qui ne fonctionne pas pour le moment? – halfer

+0

Merci pour la réponse. Si je sélectionne par exemple 5 fichiers, seul le dernier fichier est en cours de téléchargement. –

+0

Ah oui - votre contrôle d'entrée doit avoir un nom individuel - puisqu'il n'a pas de nom pour le moment, il utilise un nom par défaut pour tous les contrôles. – halfer

Répondre

15

Ceci est un problème connu as referenced on GitHub.

Comme on dit, vous devez ajouter [] à l'attribut full_name dans votre modèle:

{{ form_widget(images_form.file, { 'full_name': images_form.file.get('full_name') ~ '[]' }) }} 
+4

Dans Symfony 2.5, vous pouvez le faire en utilisant: '{{form_widget (images_form.file, {'full_name': images_form.file.vars.full_name ~ '[]'})}}' – ezpn

+0

génial! C'est la bonne réponse et elle devrait être marquée comme valide. – xger86x

+0

Merci pour le lien du problème github. Cela m'a vraiment aidé avec mon problème de validation. J'ai ajouté une autre solution en guise de réponse, ce qui fonctionne également parfaitement. – func0der

3

J'ai eu le même problème récemment, ont suivi les suggestions ici, mais nous avons eu une erreur, parce que le validateur « fichier » ne peut pas gérer les tableaux.

J'ai donc dû écrire mon propre validateur, qui peut gérer plusieurs fichiers. Pour cela, j'ai suivi this tutorial from Symfony.com, copié/collé le code du validateur 'fichier', l'ai encapsulé avec une boucle foreach et j'ai changé les variables si nécessaire.

Si vous faites cela, vous pouvez l'utiliser pour $file dans votre entité.

+4

Pouvez-vous partager ce code afin que je puisse jeter un oeil? Thnx. –

4

Je ne sais pas si cela est possible avec la syntaxe d'annotation.Donc, je vais l'écrire en PHP dans le contrôleur

$images_form = $this->createFormBuilder($file) 
    ->add('file', 'file', array(
     'constraints' => array(
      new NotBlank(), // Makes sure it is filled at all. 
      new All(array(// Validates each an every entry in the array that is uploaded with the given constraints. 
       'constraints' => array(
        new File(array(
         'maxSize' => 6000000 
        )), 
       ), 
      )), 
     ), 
     'multiple' => TRUE, 
    )) 
    ->getForm(); 

Ceci devrait fonctionner parfaitement depuis Symfony 2.4. Avant que vous auriez à mettre l'attribut multiple dans la clé attr comme vous l'avez déjà fait.

Comme je l'ai dit, vous devez faire ce travail avec des annotations. Cela pourrait fonctionner mais pourrait être moins lisible si vous deviez tout mettre en ligne. Amusez-vous;)

+0

concernant les annotations: ceci est donné à titre d'exemple sur le site Web de symfony. http://symfony.com/doc/current/reference/constraints/All.html classe 'utilisateur { /** * @Assert \ Tous ({* @Assert \ NotBlank, * @Assert \ Longueur (min = 5) *}) */ protected $ favoriteColors = array(); } ' – nexana

Questions connexes