Подтвердить что ты не робот

Проблемы с загрузкой нескольких файлов в Symfony2

Я делаю приложение Symfony2, которое должно иметь возможность загрузки нескольких изображений. Я сделал загрузку одного файла с помощью записи поваренной книги: Как обрабатывать загрузки файлов с помощью Doctrine, который отлично работает. Я выполнил lifecyclecallbacks для загрузки и удаления.

Теперь мне нужно превратить это в систему множественной загрузки. Я также прочитал несколько ответов от Stack Overflow, но ничего не работает.

Вопрос о переполнении стека:

У меня есть следующий код на данный момент:

Файл Сущность:

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

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

Я не знаю, что делать, чтобы сделать эту работу как многопользовательскую систему загрузки файлов. Я сохранил комментарии, так как они взяты из обучающих руководств, за которыми я следил, поэтому я помню, что делает.

UPDATE:

Код новой формы:

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

Код формы новой формы:

<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>
4b9b3361

Ответ 1

Это известный вопрос как указано в GitHub.

Как говорится, вы должны добавить [] к атрибуту full_name в свой шаблон:

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

Ответ 2

У меня была такая же проблема в последнее время, последовали за предложениями здесь, но получили сообщение об ошибке, потому что файл validator 'file' не может обрабатывать массивы.

Поэтому мне пришлось написать свой собственный валидатор, который может обрабатывать несколько файлов. Для этого я последовал за этим учебником от Symfony.com, скопировал/вставил код из файла валидатора в него, инкапсулировал его с помощью foreach и изменили переменные по мере необходимости.

Если вы сделаете это, вы можете использовать его для $file в своей сущности.

Ответ 3

Я не знаю, возможно ли это с синтаксисом аннотации. Поэтому я собираюсь написать его в простой PHP в контроллере

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

Это должно отлично работать с Symfony 2.4. До этого вам нужно было бы поместить атрибут multiple в ключ attr, как вы уже делали.

Как я уже сказал, вам нужно сделать эту работу с аннотациями. Он может работать, но может быть менее читаемым, если вам нужно поместить все в одну строку.

Удачи;)