422 ; * - MIME hors whitelist / fichier trop volumineux (FileUploadException) -> 422. * * Si la persistance Doctrine echoue APRES l'ecriture disque, le fichier physique * deja deplace est supprime (compensation) pour ne pas laisser de binaire orphelin. * * @implements ProcessorInterface */ final class UploadedDocumentProcessor implements ProcessorInterface { public function __construct( #[Autowire(service: 'api_platform.doctrine.orm.state.persist_processor')] private readonly ProcessorInterface $persistProcessor, private readonly FileUploader $fileUploader, private readonly RequestStack $requestStack, private readonly Security $security, ) {} public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): mixed { $request = $this->requestStack->getCurrentRequest(); $file = $request?->files->get('file'); if (!$file instanceof UploadedFile) { throw new UnprocessableEntityHttpException('Aucun fichier fourni (champ « file » attendu).'); } try { $document = $this->fileUploader->upload($file); } catch (FileUploadException $e) { // MIME hors whitelist ou fichier trop volumineux -> 422 avec le // message metier explicite porte par l'exception. throw new UnprocessableEntityHttpException($e->getMessage(), $e); } $user = $this->security->getUser(); if ($user instanceof UserInterface) { $document->setCreatedBy($user); } try { return $this->persistProcessor->process($document, $operation, $uriVariables, $context); } catch (Throwable $e) { // La persistance a echoue APRES l'ecriture disque (erreur DB, FK...) : // on supprime le fichier orphelin pour ne pas le laisser sans ligne // uploaded_document correspondante, puis on relaie l'erreur. $this->fileUploader->remove($document); throw $e; } } }