2013-09-09 2 views
9

Я попробовал новую реализацию библиотеки JQuery: dropzone.jsМульти загрузить Symfony 2.3 с Dropzone

Эта библиотека обеспечивает хороший многофункциональный интерфейс загрузки с перетаскиванием решение.

Кажется, что многопользовательская система загрузки Symfony не проста.

Я эту ошибку:

Error: Cannot use object of type Symfony\Component\HttpFoundation\File\UploadedFile as array in /vendor/symfony/symfony/src/Symfony/Component/Form/Extension/Csrf/EventListener/CsrfValidationListener.php line 87 

Моя сущность файла:

/** 
* @ORM\Entity 
* @ORM\Table(name="media__file") 
* @ORM\HasLifecycleCallbacks 
*/ 
class File 
{ 
/** 
* @ORM\Id 
* @ORM\Column(type="integer") 
* @ORM\GeneratedValue(strategy="AUTO") 
*/ 
public $id; 

/** 
* @ORM\Column(type="string", length=255) 
* @Assert\NotBlank 
*/ 
public $name; 

/** 
* @ORM\Column(type="string", length=255, nullable=true) 
*/ 
public $path; 

/** 
* @Assert\File(maxSize="6000000") 
*/ 
public $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() 
{ 

    return __DIR__.'/../../../../../web/'.$this->getUploadDir(); 
} 

protected function getUploadDir() 
{ 

    return 'uploads/files'; 
} 

/** 
* @ORM\PrePersist() 
* @ORM\PreUpdate() 
*/ 
public function preUpload() 
{ 
    if (null !== $this->file) { 
     $this->path = sha1(uniqid(mt_rand(), true)).'.'.$this->file->guessExtension(); 
    } 
} 

/** 
* @ORM\PostPersist() 
* @ORM\PostUpdate() 
*/ 
public function upload() 
{ 
    if (null === $this->file) { 
     return; 
    } 


    $this->file->move($this->getUploadRootDir(), $this->path); 

    unset($this->file); 
} 

/** 
* @ORM\PostRemove() 
*/ 
public function removeUpload() 
{ 
    if ($file = $this->getAbsolutePath()) { 
     unlink($file); 
    } 
} 

Мой контроллер FileController:

/** 
* @Route("/admin/media/upload") 
* @Template() 
*/ 
public function uploadsAction(){ 

    $file = new File(); 

    $form = $this->createForm(new \Tperroin\Bundle\MediaBundle\Form\FileUploadType(), $file); 

    if ($this->getRequest()->isMethod('POST')) { 
     $form->bind($this->getRequest()); 

     if ($form->isValid()) { 

      $em = $this->getDoctrine()->getManager(); 

      $em->persist($file); 
      $em->flush(); 

      return $this->redirect($this->generateUrl('tperroin_home_default_index')); 
     } 
    } 

return array('form' => $form->createView()); 
} 

И, наконец, мой шаблон веточка:

<div class="widget-content"> 

     <form action="{{ url('tperroin_media_file_uploads') }}" method="post" {{ form_enctype(form) }} class="dropzone"> 

      <div class="fallback"> 
       <input name="file" type="file" multiple /> 
      </div> 
     </form> 

    </div> 

EDIT:

FormType:

class FileUploadType extends AbstractType 
{ 
public function buildForm(FormBuilderInterface $builder, array $options) 
{ 
    $builder->add('file', 'file'); 
} 
public function getName() 
{ 
    return 'file'; 
} 
} 

Что случилось с моим кодом? Я знаю, что это проблема с UploadedFile и массивом, но я не знаю, как это решить.

Спасибо вам всем!

EDIT:

Может быть, эта ссылка может помочь кому-то, я не воспроизвести это:

Problems With Multiple File Upload In Symfony2

EDIT с новой функцией uploadAction:

/** 
* @Route("/upload/process", name="upload_media") 
*/ 
    public function uploadAction() 
    { 
    $request = $this->get('request'); 
    $files = $request->files;  

    $directory = $this->get('kernel')->getRootDir() . '/../web' . $this->getRequest()->getBasePath() . '/files/'; 

    foreach ($files as $uploadedFile) { 

     $name = $uploadedFile->getClientOriginalName(); 
     $file = $uploadedFile->move($directory, $name); 

     $upload = new File($name); 

     $em = $this->get('doctrine')->getManager(); 

     $em->persist($upload); 

     $em->flush(); 


    } 

    return $this->redirect($this->generateUrl('tperroin_media_default_index')); 
    } 
+0

Вы можете оставить FormType? Но, как я думаю, весь код ожидает один файл, а не несколько. –

+0

Thx! Конечно, см. Мое редактирование. Я пробовал с атрибутом «несколько», но с той же ошибкой ... –

+0

Вы не визуализируете какое-либо поле - это нормально? По крайней мере, вам нужно отобразить поле с файлом и токеном csrf. Также укажите опцию 'data_class' в форме типа –

ответ

8

Прежде всего, вы не используете свой FileUploadType в шаблоне Twig. Вы создаете форму вручную и устанавливаете путь action к URL-адресу, указанному в контроллере. Единственное, что вы используете в представлении формы, которое вы передаете шаблону, - это form_enctype. Но, как и большинство многопользовательских файлов, Dropzone, похоже, создает собственный запрос на загрузку изображения.

Это означает, что вы также должны обрабатывать входящие данные вручную.

/** 
* @Route("/admin/media/upload") 
* @Template() 
*/ 
public function showUploadAction() 
{ 
    // just show the template 
    return []; 
} 

/** 
* @Route("/admin/media/upload/process", name="upload_media") 
*/ 
public function uploadAction() 
{ 
    $request = $this->get('request'); 
    $files = $request->files; 

    // configuration values 
    $directory = //... 

    // $file will be an instance of Symfony\Component\HttpFoundation\File\UploadedFile 
    foreach ($files as $uploadedFile) { 
     // name the resulting file 
     $name = //... 
     $file = $uploadedFile->move($directory, $name); 

     // do something with the actual file 
     $this->doSomething($file); 
    } 

    // return data to the frontend 
    return new JsonResponse([]); 
} 

Метод uploadAction принимает FileBag из запроса Symfony, в итерацию над ним, и выполняет пользовательскую логику результирующего файла. Конечно, вы должны обрабатывать хранилище объекта File самостоятельно.

Ваш шаблон должен выглядеть следующим образом:

<form action="{{ path('upload_media') }}" method="post" class="dropzone"> 
    <div class="fallback"> 
     <input name="file" type="file" multiple /> 
    </div> 
</form> 


Благодаря этому вопросу я обратил внимание на пользователя Dropzone и поддержку integrated для него в OneupUploaderBundle. Таким образом, вы можете просто использовать этот комплект, который упрощает несколько шагов, упомянутых выше.

+0

Спасибо! Это решение работает, мои файлы хранятся в хорошем каталоге, но я не могу сохранить эти изображения. См. Раздел «Редактирование» с помощью функции uploadAction. Возможно, это проблема с UploadFile. Еще раз спасибо за вашу помощь –

+0

Ну, вы пытаетесь сохранить экземпляр 'Symfony \ Component \ HttpFoundation \ File \ File', который не является объектом Doctrine. Вместо этого попробуйте добавить этот файл в новый экземпляр вашего объекта 'File' и вместо этого сохранить этот объект. – devsheeep

+1

Он работает спасибо! Думаю, я понял концепцию файлов. Я проверил ваш комплект и отлично работает! –

1

Symfony требует, чтобы каждая форма содержала CSRF-токен. Ваша форма не содержит одного, поэтому symfony пытается использовать ваше поле «file» в качестве символа csrf и выдает ошибку. Первый шаг, чтобы решить эту проблему, чтобы вынести CSRF-маркер с этим фрагментом в вашей элемент формы:

{{ form_widget(form) }} 

Тогда вы должны изменить свою сущность, он может обрабатывать несколько файлов. Это можно сделать путем реализации отношения «один-много» (загрузка (одно) в файл (многие)).

+0

Это будет работать только в резервном разделе загрузчика Dropzone. – devsheeep

0

В Symfony, если у вас есть ошибка

Error: Call to a member function move() on a non-object 

изменение Try

$files = $request->files 

Для

$files = $request->files->get('file');