I have a Symfony2 application with a form where a file type field. I need to upload an image of a student there, so I helped this documentation: How to Upload Files
It is my code:
Controller:
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(),
));
}
Entity:
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);
}
}
});
});
The problem I have now is I have to do it with an Ajax request, but do not know how to send that file field and it can be used then in Symfony controller.
I have seen some FormData()
, but do not know how it is used.
Could you help me?
Ajax file uploadsA component must exist on the server to handle the file upload and save the resource locally; The server must send a response to the browser indicating the JavaScript file upload was successful; and. The client's browser must provide an Ajax-based response indicating the file uploaded successfully.
Uploading Files in MVC using jQuery AJAX FormDataGo to File->New->Project. Give a suitable name to the Application. Click OK. As you can see in the above image, two files are sent to C# ActionMethod, and both will be uploaded now.
I've solved changing in my code:
data: new FormData($(this)[0])
instead of data: $ (this).serialize()
Adding the ajax request:
processData: false,
contentType: false,
cache: false,
and the file is sent correctly
I have solve this in following way, if you want to do it using Ajax.
In your entity declare this :
/**
*@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);
}
}
}
In your FormType :
->add('file', null, array('label' => 'Profile Picture', 'required' => false))
In you Controller :
$entity->setFile($request->files->get('photo')); //here you have get your file field name
$em->persist($entity);
$em->flush();
your ajax looks fine, but if this will not work than use
data:new FormData(this),
instead of
data: $(this).serialize(),
and add these two parameters in ajax:
processData: false,
contentType: false
You can change save file method as your requirement and change path field to photo.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With