Symfony2:使用Ajax和jQuery上传文件

我有一个Symfony2应用程序,其中包含一个文件类型字段的表单。 我需要在那里上传一个学生的图像,所以我帮助了这个文档: 如何上传文件

这是我的代码:

控制器:

public function createAction(Request $request) { if ($request->isXmlHttpRequest() && !$request->isMethod('POST')) { throw new HttpException('XMLHttpRequests/AJAX calls must be POSTed'); } $entity = new Student(); $form = $this->createCreateForm($entity); $form->handleRequest($request); if ($form->isValid()) { $file = $entity->getPhoto(); $fileName = md5(uniqid()).'.'.$file->guessExtension(); $photoDir = $this->container->getParameter('kernel.root_dir').'/../web/uploads/images'; $file->move($photoDir, $fileName); $entity->setPhoto($fileName); $em = $this->getDoctrine()->getManager(); $em->persist($entity); $em->flush(); if ($request->isXmlHttpRequest()) { return new JsonResponse(array('message' => 'Success!','success' => true), 200); } if ($request->isMethod('POST')) { return new JsonResponse(array('message' => 'Invalid form','success' => false), 400); } return $this->redirect($this->generateUrl('student_show', array('id' => $entity->getId()))); } return $this->render('BackendBundle:Student:new.html.twig', array( 'entity' => $entity, 'form' => $form->createView(), )); } 

实体:

  use Doctrine\ORM\Mapping as ORM; use Symfony\Component\Validator\Constraints as Assert; //... /** * @var string * * @ORM\Column(name="photo", type="string", length=255, nullable=true) * */ private $photo; public function setPhoto($photo) { $this->photo = $photo; return $this; } public function getPhoto() { return $this->photo; } 

formtype:

  //... ->add('photo', 'file', array('required' => false)) //... 

使用Javascript:

  //... $('.form_student').on("submit",function(event) { event.preventDefault(); $.ajax({ type: 'POST', url: Routing.generate('student_create'), data: $(this).serialize(), dataType: 'json', success: function(response) { alert(response.message); }, error: function (response, desc, err){ if (response.responseJSON && response.responseJSON.message) { alert(response.responseJSON.message); } else{ alert(desc); } } }); }); 

我现在遇到的问题是我必须使用Ajax请求,但不知道如何发送该文件字段,然后可以在Symfony控制器中使用它。

我见过一些FormData() ,但不知道它是如何使用的。

你可以帮帮我吗?

我已经解决了改变我的代码:

  • data: new FormData($(this)[0])而不是data: $ (this).serialize()

  • 添加ajax请求:

    processData: false, contentType: false, cache: false,

并正确发送文件

如果你想使用Ajax,我可以通过以下方式解决这个问题。

在您的实体中声明:

 /** *@ORM\HasLifecycleCallbacks */ class Student { /** * @ORM\Column(type="string", length=255, nullable=true) */ public $path; /** * @Assert\File( * maxSize="60000", * ) */ private $file; private $temp; /** * Sets file. * * @param UploadedFile $file */ public function setFile(UploadedFile $file = null) { $this->file = $file; if (isset($this->path)) { // store the old name to delete after the update $this->temp = $this->path; $this->path = null; } else { $this->path = 'initial'; } } /** * Get file. * * @return UploadedFile */ public function getFile() { return $this->file; } public function getAbsolutePath() { return null === $this->path ? null : $this->getUploadRootDirPath().'/'.$this->path; } public function getWebPath() { return null === $this->path ? null : $this->getUploadDirPath().'/'.$this->path; } protected function getUploadRootDirPath() { // the absolute directory path where uploaded // documents should be saved return __DIR__.'/../../../../web/'.$this->getUploadDirPath(); } protected function getUploadDirPath() { // get rid of the __DIR__ so it doesn't screw up // when displaying uploaded doc/image in the view. return 'uploads/student_photos'; } /** * @ORM\PrePersist() * @ORM\PreUpdate() */ public function preUpload() { if (null !== $this->getFile()) { // do whatever you want to generate a unique name $filename = basename($this->getFile()->getClientOriginalName(),'.'.$this->getFile()->getClientOriginalExtension()); $this->path = $filename.'.'.$this->getFile()->getClientOriginalExtension(); if(file_exists($this->getUploadRootDirPath().'/'.$this->path)==1) { $date = date('-d_M_Y_H:i'); $this->path = $filename.$date.'.'.$this->getFile()->getClientOriginalExtension(); } } } /** * @ORM\PostPersist() * @ORM\PostUpdate() */ public function upload() { if (null === $this->getFile()) { return; } $this->getFile()->move($this->getUploadRootDirPath(), $this->path); if (isset($this->temp)) { // delete the old image unlink($this->getUploadRootDirPath().'/'.$this->temp); // clear the temp image path $this->temp = null; } $this->file = null; } /** * @ORM\PostRemove() */ public function removeUpload() { $file = $this->getAbsolutePath(); if ($file) { unlink($file); } } } 

在您的FormType中:

 ->add('file', null, array('label' => 'Profile Picture', 'required' => false)) 

在你的控制器:

  $entity->setFile($request->files->get('photo')); //here you have get your file field name $em->persist($entity); $em->flush(); 

你的ajax看起来很好,但如果这不会比使用更好

  data:new FormData(this), 

代替

  data: $(this).serialize(), 

并在ajax中添加这两个参数:

  processData: false, contentType: false 

您可以根据需要更改保存文件方法,并将路径字段更改为照片。

更新:

我认为问题在于,如果您通过ajax提交,则必须在控制器中反序列化收到的内容

相应地,您应该明确地序列化表单,而不是使用此序列化

 var data= $('form.form_student').serialize();