I've been trying to use VichUploader to upload files on a Symfony project, already using EasyAdmin 3.
I've configured everything correctly, but I'm getting this error:
The "pieceJointeFile" image field must define the directory where the images are uploaded using the setUploadDir() method.
<?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="integer")
     */
    private $id;
    /**
     * @ORM\ManyToOne(targetEntity=Conducteur::class, inversedBy="inventaires")
     */
    private $conducteur;
    /**
     * @ORM\Column(type="date")
     */
    private $dateInventaire;
    /**
     * @ORM\Column(type="string", length=255)
     */
    private $pieceJointe;
    /**
     * @Vich\UploadableField(mapping="pieceJointe", fileNameProperty="pieceJointe")
     */
    private $pieceJointeFile;
    /**
     * @ORM\Column(type="datetime")
     */
    private $updatedAt;
    public function __construct()
    {
        $this->updatedAt = new DateTime();
    }
    public function getId(): ?int
    {
        return $this->id;
    }
    public function getConducteur(): ?Conducteur
    {
        return $this->conducteur;
    }
    public function setConducteur(?Conducteur $conducteur): self
    {
        $this->conducteur = $conducteur;
        return $this;
    }
    public function getDateInventaire(): ?\DateTimeInterface
    {
        return $this->dateInventaire;
    }
    public function setDateInventaire(\DateTimeInterface $dateInventaire): self
    {
        $this->dateInventaire = $dateInventaire;
        return $this;
    }
    public function getPieceJointeFile() {
        return $this->pieceJointeFile;
    }
    public function setPieceJointeFile($pieceJointeFile): void
    {
        $this->pieceJointeFile = $pieceJointeFile;
        if($pieceJointeFile) {
            $this->updatedAt = new DateTime();
        }
    }
    public function getPieceJointe() {
        return $this->pieceJointe;
    }
    public function setPieceJointe($pieceJointe):self
    {
        $this->pieceJointe = $pieceJointe;
        return $this;
    }
    public function getUpdatedAt()
    {
        return $this->updatedAt;
    }
}
vich uploader configuration
vich_uploader:
    db_driver: orm
    mappings:
        pieceJointe:
            uri_prefix: /files/pieceJointe
            upload_destination: '%kernel.project_dir%/public/files/pieceJointe'
and finally My crud controller
<?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')->setFormType(VichFileType::class, [
                'delete_label' => 'supprimer?'
            ])->onlyOnForms(),
            ImageField::new('pieceJointe')->setBasePath('/files/pieceJointe')->onlyOnDetail(),
            ImageField::new('pieceJointeFile')->setFormType(VichImageType::class)
        ];
    }
    public function configureActions(Actions $actions): Actions
    {
        return $actions
            ->add(Crud::PAGE_INDEX, Action::DETAIL);
    }
}
Finally, I want to clarify that when using TextField it works correctly.
 
     
     
     
     
     
     
     
    