我尝试了一个新的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>
编辑:
FormType:
class FileUploadType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('file', 'file');
}
public function getName()
{
return 'file';
}
}
我的代码出了什么问题?我知道这是UploadedFile和数组的问题,但我不知道如何解决这个问题。
谢谢大家!
编辑:
也许这个链接可以帮助某人,我无法重现这个:
Problems With Multiple File Upload In 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'));
}
答案 0 :(得分:8)
首先,您并未在Twig模板中真正使用FileUploadType
。您手动创建表单并将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([]);
}
方法uploadAction
从Symfony的请求中获取FileBag
,迭代它,并在生成的文件上执行自定义逻辑。当然,您必须自己处理File
实体的存储。
您的模板应如下所示:
<form action="{{ path('upload_media') }}" method="post" class="dropzone">
<div class="fallback">
<input name="file" type="file" multiple />
</div>
</form>
<小时/> 感谢这个问题,我注意到了Dropzone上传者以及integrated对OneupUploaderBundle的支持。所以你可以使用这个包简化了上面提到的几个步骤。
答案 1 :(得分:1)
Symfony要求每个表单都包含一个csrf-token。您的表单不包含一个,因此symfony尝试使用您的“文件”-field作为csrf-token并抛出错误。 解决此问题的第一步是在表单元素中使用此代码段呈现csrf-token:
{{ form_widget(form) }}
然后你必须改变它可以处理多个文件的实体。这可以通过实现一对多关系(上传(一)到文件(很多))来完成。
答案 2 :(得分:0)
如果您有错误,请在Symfony中
Error: Call to a member function move() on a non-object
尝试更改
$files = $request->files
要
$files = $request->files->get('file');