Basic settings
To create a simple doctrine entity class:
src/acme/demobundle/entity/document.php namespace acme\demobundle\entity;
use doctrine\orm\mapping as orm;
use symfony\component\validator\constraints as assert; /** * @ORM \entity */class document { /** * @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) */   &Nbsp;public $path; public function getabsolutepath () { return null === $this->path ? null : $this->getuploadrootdir (). '
/'. $this->path;    &NBSP} public function getwebpath ()
{ return null === $this->path ? null : $this->getuploaddir (). '
/'. $this->path;    &NBSP} protected function getuploadrootdir () {  &NBsp; // the absolute directory path where uploaded // documents should be saved return __dir__. ' /.. /.. /.. /..
/web/'. $this->getuploaddir ();    &NBSP} protected function getuploaddir () { // get rid of the __dir_ _ SO IT DOESN ' T screw up // when
displaying uploaded doc/image in the view.
return ' uploads/documents ';    &NBSP}}
The document entity has a name associated with the file. This path property stores the relative path of a file and is stored in the database. This getabsolutepath () returns an absolute path, and Getwebpath () returns a web path for the template to join the upload file link.
If you haven't done so, you should read http://symfony.com/doc/current/reference/forms/types/file.html first to understand the basic upload process.
If you use annotations to validate a rule (as shown in this example), make sure that you have enabled annotation validation (see Http://symfony.com/doc/current/book/validation.html#book-validation-configuration).
When processing an actual file upload, use a "virtual" file field. For example, if you build a form directly in controller, he might be like this:
Public function uploadaction () { // $ form = $this->createformbuilder ($document) -> Add (' name ') ->add (' file ')
->getform ();
    //&NBSP ...}
Next, create the File attribute into your document class and add some validation rules: use symfony\component\httpfoundation\file\uploadedfile; //  class document { /** * @Assert \
File (maxsize= "6000000") */ private $file;
/** * sets file. * * @param UploadedFile $file */ public function setFile (uploadedfile $file = null) {
$this->file = $file;
   &NBSP} /** * get file. * * @return uploadedfile */ public function getfile () {
return $this->file;    &NBSP}} annotations annotations// src/acme/demobundle/entity/document.php namespace
acme\demobundle\entity;
//&NBSP ... use symfony\component\validator\constraints as assert; Class document { /** * @Assert \file (maxSize
= "6000000") */ private $file; &NBSp; // .}
When you use the file constraint, Symfony automatically guesses that the form field is entered as a file upload. This is why when you create a form (->add (' file ')), why it is not explicitly set in the form as a file upload.
The following controller tells you how to handle the whole process:
use acme\demobundle\entity\document;.
use sensio\bundle\frameworkextrabundle\configuration\template;
use symfony\component\httpfoundation\request;   /** * @Template () */public function uploadaction (request $ Request) { $document = new document () $form
= $this->createformbuilder ($document) ->add (' name ') ->add (' file ')
->getform ();
$form->handlerequest ($request); if ($form->isvalid ()) {
$em = $this->getdoctrine ()->getmanager ();
$em->persist ($document); $em->flush (); return $this->redirect ($this->generateurl (...)
));    &NBSP} return array (' form ' => $form->
CreateView ()); }
The previous controller when the name automatic Storage document entity was submitted, but he would not do anything about the file and the path attribute would be blank.
A simple way to process file uploads is to set the path attribute before entity is persisted. When handling file uploads at some point, you call the document entity class with a upload () method that assigns a value to the path.
if ($form->isvalid ()) { $em = $this->getdoctrine ()->
GetManager ();
$document->upload ();
$em->persist ($document);
$em->flush ();
return $this->redirect (...); This upload () method utilizes the UploadedFile object, which returns the file field after it is committed: Public function upload () { // the file property can be empty if the field is not required // The File property is empty This property does not need if (null === $this->getfile ()) { return; &NBSP} // use the original file name here but you should     // SANITIZE IT AT LEAST TO AVOID&NBSp;any security issues // Here you should use the original filename but should at least audit it to avoid some security issues // move takes the target directory and then the // target filename to move to // Move the target file to the target directory $this->getfile ()->move ( $this->getuploadrootdir (), $this->getfile ()->
Getclientoriginalname () ); // set the path property to the filename where you ' Ve saved the file // Set the Path property to save the file name for you
$this->path = $this->getfile ()->getclientoriginalname ();     // CLEAN UP THE FILE PROPERTY AS  You won ' T need it anymore // clean up the file properties you don't need
$this->file = null; Using the lifecycle callback lifecycle callback is a limited technique, and he has some drawbacks. If you want to remove the write-dead encoding __dir__ in the Document::getuploadrootdir () method, the best approach is to start using doctrine listeners.
Where you will be able to inject kernel parameters, such as Kernel.root_dir, to establish an absolute path. Working on this principle, he has a flaw: what is the problem when entity is persisted?
A: The file has been transferred to its final location, and the path attribute under the entity class cannot be properly materialized. (If Entity has persistent problems or files cannot be moved and nothing happens) in order to avoid these problems, you should change the implementation so that the database operates and automatically deletes files:/** * @ORM \entity * @ORM \haslifecyclecallbacks */class document {}
Next, use these callback functions to refactor the document class:
use symfony\component\httpfoundation\file\uploadedfile; /** * @ORM \entity * @ORM \haslifecyclecallbacks */class document {
private $temp;
/** * sets file. * * @param UploadedFile $file */ public function setfile (UploadedFile $file = null) { $this->file
= $file; // check if we have an old Image path // Check if we have an old picture path if (Isset ($this->path)) { &nbSp;// store the old name to delete after the update
$this->temp = $this->path;
$this->path = null; } else {
$this->path = ' initial ';
       &NBSP} } /**
* @ORM \prepersist () * @ORM \preupdate () */ public function preupload () { if (null !== $this->getfile ()) { &Nbsp; // do whatever you want to generate a unique name // to generate a unique name $filename = sha1 (Uniqid (Mt_rand (), true)
; $this->path = $filename.
$this->getfile ()->guessextension ();
       &NBSP} } /**
* @ORM \postpersist () * @ORM \postupdate () */ public function upload ()
{ if (null === $this->getfile ()) { reTurn        &NBSP} // if there is an error when moving the file, an Exception will // be automatically thrown by move (). this will properly prevent // the entity from being persisted to the database on
Error //an exception move () throws an exception automatically when the file is moved incorrectly.
//this will prevent an entity from persisting an error in the database. $this->getfile ()->move ($this->getuploadrootdir (),
$this->path); // check if we have an old image if (Isset ($this->temp)) { // delete the old image unlink ($this->getuploadrootdir (). '
/'. $this->temp); // clear the temp Image path $this->temp =
null;        &NBSP} $this->
file = null;    &NBSP} /** * @ORM \postremove () */ public function removeupload ()
{ $file = $this->getabsolutepath (); if ($file) {
unlink ($file); }  }}
If you change your entity is handled by doctrine event listener or event subscriber, this preupdate () callback function must notify doctrine about the changes being made. For a complete reference to the Preupdate event limit, see the Http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/events.html#preupdate
Now this class does everything you need: He will generate a unique filename before entity is persisted, move the file, and delete the file.
Moving the file now is entity automatically, and this $document->upload () should be removed from the controller:
if ($form->isvalid ()) {
$em = $this->getdoctrine ()->getmanager ();
$em->persist ($document);
$em->flush ();
return
$this->redirect (...);
}
This @orm\prepersist () and @orm\postpersist () event callback: One is triggered before the entity is persisted to the database, and one is triggered after the entity is persisted to the database. On the other hand, @ORM \preupdate () and @ORM \postupdate () event callbacks are triggered when an entity is updated.
The Preupdate and postupdate callbacks are triggered when the entity field is changed after the persistence operation. This means that by default you only change the $file property, and these events will not be triggered because the property itself will not be persisted to doctrine. One workaround is to create a updated field to persist it to doctrine and adjust it manually when the file changes.
Use ID as file name
If you want to use an ID as a file name, and the implementation is slightly different, you need to save the Path property to the file extension instead of the actual file name:
use symfony\component\httpfoundation\file\uploadedfile; /** * @ORM \entity * @ORM \haslifecyclecallbacks */class document {
private $temp;
/** * sets file. * * @param UploadedFile $file */ public function setfile (UploadedFile $file = null) { $this->file
= $file; // check if we have an old Image path if (Is_file ($this->getabsolutepath ())) { // store the old name to d elete after the update
$this->temp = $this->getabsolutepath (); } else {
$this->path = ' initial ';
       &NBSP} } /**
* @ORM \prepersist () * @ORM \preupdate () */ public function preupload () { if (null !== $this->getfile ()) { $this->path = $
This->getfile ()->guessextension (); } } /** * @ORM \postpersist () * @ORM \postupdate () */ public Function upload () { if (null === $this->getfile ()) {
return;        &NBSP} // check if we have an old image if (Isset ($this->temp)) { // delete the old image
unlink ($this->temp); // clear the temp image path
$this->temp = null;        &NBSP} // you must throw an exception here if the file cannot be moved // so that the entity is not persisted to the database // which the uploadedfile move () method does $this->getfile ()->move ( $this->getuploadrootdir (), $ This->id. '. '. $this->getfile ()->guessextension () );
$this->setfile (null);    &NBSP} /** * @ORM \preremove (
) */ public function storefilenameforremove () { $this->temp = $this->
GetAbsolutePath ();    &NBSP} /** * @ORM \postremove () */ public function removeupload () { if (isset ($this->temp)) {
unlink ($this->temp);        &NBSP} } public fUnction getabsolutepath () { return null === $this->path ? null : $this-> Getuploadrootdir (). ' /'. $this->id. '.
$this->path;    &NBSP}}
You will notice that in this case you need to do a little work to delete the file. Before the data is deleted, you must save the file path (because it depends on the ID). Then, once the object has been completely removed from the database, you can safely delete the file (after the data has been deleted).