10

我尝试了 JQuery 库的新实现:dropzone.js

这个库提供了一个很好的多上传界面和拖放解决方案。

看来 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>

编辑 :

表单类型:

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

我的代码有什么问题?我知道这是 UploadedFile 和数组的问题,但我不知道如何解决。

感谢你所做的一切 !

编辑 :

也许这个链接可以帮助某人,我无法重现这个:

Symfony2 中多个文件上传的问题

使用新的 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'));
   }
4

3 回答 3

8

首先,您并没有真正FileUploadType在 Twig 模板中使用您的。您手动创建一个表单并将action路径设置为您在 Controller 中定义的 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([]);
}

该方法从 Symfony 的请求中uploadAction获取FileBag,对其进行迭代,并在结果文件上执行您的自定义逻辑。当然,您必须自己处理File实体的存储。

您的模板应如下所示:

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


由于这个问题,我注意到了 Dropzone 上传器并在 OneupUploaderBundle集成了对它的支持。所以你可以只使用这个包,它简化了上面提到的几个步骤。

于 2013-09-18T11:12:52.533 回答
1

Symfony 要求每个表单都包含一个 csrf-token。您的表单不包含一个,因此 symfony 尝试使用您的“文件”字段作为 csrf 令牌并抛出错误。解决此问题的第一步是在表单元素中使用此代码段呈现 csrf-token:

{{ form_widget(form) }}

然后你必须改变你的实体,它可以处理多个文件。这可以通过实现一对多关系(上传(一)到文件(多))来完成。

于 2013-09-16T16:08:15.373 回答
0

如果你有错误,在 Symfony 中

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

尝试改变

$files = $request->files

$files = $request->files->get('file');
于 2015-03-05T08:31:12.477 回答