title: How to use Vich uploader with easyAdmin 3 on Symfony 5
body: <p>I've been trying to use VichUploader to upload files on a Symfony project, already using EasyAdmin 3.</p>
  <p>I've configured everything correctly, but I'm getting this error:</p>
  <blockquote>
  <p>The &quot;pieceJointeFile&quot; image field must define the directory where the
  images are uploaded using the setUploadDir() method.</p>
  </blockquote>
  <pre><code>&lt;?php
  
  namespace App\Entity;
  
  use App\Repository\InventaireRepository;
  use DateTime;
  use Doctrine\ORM\Mapping as ORM;
  use Symfony\Component\HttpFoundation\File\File;
  use Vich\UploaderBundle\Mapping\Annotation as Vich;
  
  My entity
  
  /**
   * @ORM\Entity(repositoryClass=InventaireRepository::class)
   * @Vich\Uploadable
   */
  class Inventaire
  {
      /**
       * @ORM\Id
       * @ORM\GeneratedValue
       * @ORM\Column(type=&quot;integer&quot;)
       */
      private $id;
  
      /**
       * @ORM\ManyToOne(targetEntity=Conducteur::class, inversedBy=&quot;inventaires&quot;)
       */
      private $conducteur;
  
      /**
       * @ORM\Column(type=&quot;date&quot;)
       */
      private $dateInventaire;
  
      /**
       * @ORM\Column(type=&quot;string&quot;, length=255)
       */
      private $pieceJointe;
  
      /**
       * @Vich\UploadableField(mapping=&quot;pieceJointe&quot;, fileNameProperty=&quot;pieceJointe&quot;)
       */
      private $pieceJointeFile;
  
      /**
       * @ORM\Column(type=&quot;datetime&quot;)
       */
      private $updatedAt;
  
      public function __construct()
      {
          $this-&gt;updatedAt = new DateTime();
      }
  
      public function getId(): ?int
      {
          return $this-&gt;id;
      }
  
      public function getConducteur(): ?Conducteur
      {
          return $this-&gt;conducteur;
      }
  
      public function setConducteur(?Conducteur $conducteur): self
      {
          $this-&gt;conducteur = $conducteur;
  
          return $this;
      }
  
      public function getDateInventaire(): ?\DateTimeInterface
      {
          return $this-&gt;dateInventaire;
      }
  
      public function setDateInventaire(\DateTimeInterface $dateInventaire): self
      {
          $this-&gt;dateInventaire = $dateInventaire;
  
          return $this;
      }
  
      public function getPieceJointeFile() {
          return $this-&gt;pieceJointeFile;
      }
  
      public function setPieceJointeFile($pieceJointeFile): void
      {
          $this-&gt;pieceJointeFile = $pieceJointeFile;
  
          if($pieceJointeFile) {
              $this-&gt;updatedAt = new DateTime();
          }
      }
  
      public function getPieceJointe() {
          return $this-&gt;pieceJointe;
      }
  
  
      public function setPieceJointe($pieceJointe):self
      {
          $this-&gt;pieceJointe = $pieceJointe;
          return $this;
      }
  
      public function getUpdatedAt()
      {
          return $this-&gt;updatedAt;
      }
  }
  </code></pre>
  <p>vich uploader configuration</p>
  <pre><code>vich_uploader:
      db_driver: orm
  
      mappings:
          pieceJointe:
              uri_prefix: /files/pieceJointe
              upload_destination: '%kernel.project_dir%/public/files/pieceJointe'
  </code></pre>
  <p>and finally My crud controller</p>
  <pre><code>&lt;?php
  
  namespace App\Controller\Admin;
  
  use App\Entity\Inventaire;
  use EasyCorp\Bundle\EasyAdminBundle\Config\Action;
  use EasyCorp\Bundle\EasyAdminBundle\Config\Actions;
  use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
  use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
  use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField;
  use EasyCorp\Bundle\EasyAdminBundle\Field\DateField;
  use EasyCorp\Bundle\EasyAdminBundle\Field\ImageField;
  use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
  use Vich\UploaderBundle\Form\Type\VichFileType;
  use Vich\UploaderBundle\Form\Type\VichImageType;
  
  class InventaireCrudController extends AbstractCrudController
  {
      public static function getEntityFqcn(): string
      {
          return Inventaire::class;
      }
  
  
      public function configureFields(string $pageName): iterable
      {
          return [
              DateField::new('dateInventaire'),
              AssociationField::new('conducteur'),
              TextField::new('pieceJointeFile')-&gt;setFormType(VichFileType::class, [
                  'delete_label' =&gt; 'supprimer?'
              ])-&gt;onlyOnForms(),
              ImageField::new('pieceJointe')-&gt;setBasePath('/files/pieceJointe')-&gt;onlyOnDetail(),
              ImageField::new('pieceJointeFile')-&gt;setFormType(VichImageType::class)
          ];
      }
  
  
  
      public function configureActions(Actions $actions): Actions
      {
          return $actions
              -&gt;add(Crud::PAGE_INDEX, Action::DETAIL);
      }
  }
  </code></pre>
  <p>Finally, I want to clarify that when using <code>TextField</code> it works correctly.</p>