У меня есть приложение 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); } } }); });
по//... $('.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
Добавим, что вы должны сериализовать форму явным образом, а не сериализовать, используя this
var data= $('form.form_student').serialize();