diff --git a/src/Controller/UploadController.php b/src/Controller/UploadController.php
index ed4e974ec10b309596baeed97f6c1848e2d618d0..1b62168a1f75324b611322eb57b2fa276db3cab6 100644
--- a/src/Controller/UploadController.php
+++ b/src/Controller/UploadController.php
@@ -100,11 +100,9 @@ class UploadController extends Controller
 
         $file = $this->fileManager->create(
             $data['name'],
-            $data['size'],
+            (int) $data['size'],
             $data['type'],
-            $data['lastModified'] ?? null,
-            $token !== null ? $token->getUsername() : null,
-            $request->getClientIp()
+            (int) $data['lastModified'] ?: null
         );
 
         $parameters = ['id' => $file->getId()];
diff --git a/src/Entity/UploadedFile.php b/src/Entity/UploadedFile.php
index 20c5b3d0131a7494284010451239c873f65be3e8..3f2bf22f496cbda7ee0831add6f67f111ff1cd57 100644
--- a/src/Entity/UploadedFile.php
+++ b/src/Entity/UploadedFile.php
@@ -17,7 +17,7 @@ use Irstea\FileUploadBundle\Utils\MimeTypeIcon;
 use Rhumsaa\Uuid\Uuid;
 
 /**
- * @ORM\Entity(repositoryClass="Irstea\FileUploadBundle\Entity\Repository\UploadedFileRepository")
+ * @ORM\Entity
  * @ORM\EntityListeners({
  *  "Irstea\FileUploadBundle\Listener\UploadedFileListener",
  *  "Irstea\FileUploadBundle\Listener\CreationDataListener"
@@ -351,15 +351,11 @@ class UploadedFile implements UploadedFileInterface
     /**
      * @param Filesystem $filesystem
      *
-     * @return self
-     *
      * @internal
      */
-    public function setFilesystem(Filesystem $filesystem)
+    public function setFilesystem(Filesystem $filesystem): void
     {
         $this->filesystem = $filesystem;
-
-        return $this;
     }
 
     /**
diff --git a/src/Model/FileManagerInterface.php b/src/Model/FileManagerInterface.php
index 23fac27625a734928729e45f8e0fb54b53dd06fe..35034be6a117e2d10c651fca68893126fba78ed5 100644
--- a/src/Model/FileManagerInterface.php
+++ b/src/Model/FileManagerInterface.php
@@ -21,7 +21,7 @@ interface FileManagerInterface
      *
      * @api
      */
-    public function get($id);
+    public function get($id): ?UploadedFileInterface;
 
     /** Crée un nouveau fichier uploadé, vide.
      * Le fichier est créé à l'état UploadedFileInterface::ETAT_EN_COURS.
@@ -35,7 +35,7 @@ interface FileManagerInterface
      *
      * @api
      */
-    public function create($name, $size, $mimeType, $lastModified = null);
+    public function create(string $name, int $size, string $mimeType, int $lastModified = null): UploadedFileInterface;
 
     /** Duplique un fichier.
      * N'accepte que des fichiers valides.
@@ -49,7 +49,7 @@ interface FileManagerInterface
      *
      * @api
      */
-    public function duplicate(UploadedFileInterface $original);
+    public function duplicate(UploadedFileInterface $original): UploadedFileInterface;
 
     /** Supprime un fichier uploadé.
      * *Attention :* le fichier est supprimé du disque !
@@ -58,7 +58,7 @@ interface FileManagerInterface
      *
      * @api
      */
-    public function delete(UploadedFileInterface $file);
+    public function delete(UploadedFileInterface $file): void;
 
     /** Indique que l'upload d'un fichier est terminé.
      * Cela passe le fichier à l'état UploadedFileInterface::ORPHELIN et provoque la mise-à-jour de la taille, du
@@ -68,7 +68,7 @@ interface FileManagerInterface
      *
      * @internal
      */
-    public function completed(UploadedFileInterface $file);
+    public function completed(UploadedFileInterface $file): void;
 
     /** Retourne une liste de fichiers invalides à supprimer.
      * Ce sont des fichiers partiels ou orphelin qui n'ont pas été modifiés depuis plus d'une heure.
@@ -77,12 +77,12 @@ interface FileManagerInterface
      *
      * @internal
      */
-    public function findGarbage();
+    public function findGarbage(): array;
 
     /** Retourne la liste des fichiers à valider.
      * @return UploadedFileInterface[]
      *
      * @internal
      */
-    public function findFilesToValidate();
+    public function findFilesToValidate(): array;
 }
diff --git a/src/Model/UploadedFileInterface.php b/src/Model/UploadedFileInterface.php
index c5dfd15ca902b863101901647184e21ce1798972..154ff474d3104184694ced04043ed223518693d9 100644
--- a/src/Model/UploadedFileInterface.php
+++ b/src/Model/UploadedFileInterface.php
@@ -7,6 +7,7 @@
 namespace Irstea\FileUploadBundle\Model;
 
 use DateTime;
+use Gaufrette\Filesystem;
 
 /** Un fichier uploadé.
  */
@@ -360,4 +361,9 @@ interface UploadedFileInterface
      * @api
      */
     public function hasSameContent(UploadedFileInterface $other);
+
+    /**
+     * @param Filesystem $fs
+     */
+    public function setFilesystem(Filesystem $fs): void;
 }
diff --git a/src/Resources/config/services.yml b/src/Resources/config/services.yml
index d56ab5ed6fc2cdfc554ea52114edfcd0b36b7df5..46cc82481a997f947892ac0f1027f684ec3ed9a5 100644
--- a/src/Resources/config/services.yml
+++ b/src/Resources/config/services.yml
@@ -18,14 +18,13 @@ services:
 
     # Le gestionnaire de fichiers
     irstea_file_upload.file_manager:
-        class: Irstea\FileUploadBundle\Entity\Repository\UploadedFileRepository
-        factory:  [ "@Doctrine\\Common\\Persistence\\ObjectManager", getRepository ]
+        class: Irstea\FileUploadBundle\Service\FileManager
         arguments:
+            - "@irstea_file_upload.filesystem"
+            - "@event_dispatcher"
+            - "@doctrine"
             - "%irstea_file_upload.entity%"
-        calls:
-            - [ setFilesystem, [ "@irstea_file_upload.filesystem" ] ]
-            - [ setLogger, [ "@logger" ] ]
-            - [ setEventDispatcher, [ "@event_dispatcher" ] ]
+            - "@logger"
         public: true
         tags:
             - { name: monolog.logger, channel: irstea_file_upload }
diff --git a/src/Entity/Repository/UploadedFileRepository.php b/src/Service/FileManager.php
similarity index 57%
rename from src/Entity/Repository/UploadedFileRepository.php
rename to src/Service/FileManager.php
index 281349202b4dca2bdfc0904b1b55e59268bbd946..bf836ea5af7ca3aea321ba1541522df188518ef5 100644
--- a/src/Entity/Repository/UploadedFileRepository.php
+++ b/src/Service/FileManager.php
@@ -4,9 +4,10 @@
  * All rights reserved.
  */
 
-namespace Irstea\FileUploadBundle\Entity\Repository;
+namespace Irstea\FileUploadBundle\Service;
 
 use DateTime;
+use Doctrine\ORM\EntityManagerInterface;
 use Doctrine\ORM\EntityRepository;
 use Gaufrette\Filesystem;
 use Gaufrette\StreamMode;
@@ -17,54 +18,70 @@ use Irstea\FileUploadBundle\Exception\RejectedFileException;
 use Irstea\FileUploadBundle\FileUploadEvents;
 use Irstea\FileUploadBundle\Model\FileManagerInterface;
 use Irstea\FileUploadBundle\Model\UploadedFileInterface;
-use Psr\Log\LoggerAwareTrait;
+use Psr\Log\LoggerInterface;
 use Psr\Log\LogLevel;
+use Psr\Log\NullLogger;
 use Rhumsaa\Uuid\Uuid;
-use Symfony\Component\EventDispatcher\EventDispatcher;
+use Symfony\Bridge\Doctrine\RegistryInterface;
 use Symfony\Component\EventDispatcher\EventDispatcherInterface;
 
 /**
- * Class UploadedFileRepository.
+ * Class FileManager.
  */
-class UploadedFileRepository extends EntityRepository implements FileManagerInterface
+final class FileManager implements FileManagerInterface
 {
-    use LoggerAwareTrait;
-
     /**
      * @var Filesystem
      */
-    protected $filesystem;
+    private $filesystem;
 
     /**
-     * @var EventDispatcher
+     * @var EventDispatcherInterface
      */
-    protected $eventDispatcher;
+    private $eventDispatcher;
 
     /**
-     * @param Filesystem $filesystem
+     * @var LoggerInterface
      */
-    public function setFilesystem(Filesystem $filesystem)
-    {
-        $this->filesystem = $filesystem;
-    }
+    private $logger;
 
     /**
+     * @var EntityManagerInterface
+     */
+    private $entityManager;
+
+    /**
+     * @var EntityRepository
+     */
+    private $repository;
+
+    /**
+     * FileManager constructor.
+     *
+     * @param Filesystem               $filesystem
      * @param EventDispatcherInterface $eventDispatcher
+     * @param RegistryInterface        $doctrine
+     * @param string                   $entityClass
+     * @param LoggerInterface          $logger
      */
-    public function setEventDispatcher(EventDispatcherInterface $eventDispatcher)
-    {
+    public function __construct(
+        Filesystem $filesystem,
+        EventDispatcherInterface $eventDispatcher,
+        RegistryInterface $doctrine,
+        string $entityClass,
+        LoggerInterface $logger = null
+    ) {
+        $this->filesystem = $filesystem;
         $this->eventDispatcher = $eventDispatcher;
+        $this->logger = $logger ?: new NullLogger();
+        $this->entityManager = $doctrine->getEntityManagerForClass($entityClass);
+        $this->repository = $this->entityManager->getRepository($entityClass);
     }
 
     /**
-     * @param string $filename
-     * @param int    $size
-     * @param string $mimeType
-     * @param null   $lastModified
-     *
-     * @return UploadedFile
+     * {@inheritdoc}
      */
-    public function create($filename, $size, $mimeType, $lastModified = null)
+    public function create(string $filename, int $size, string $mimeType, int $lastModified = null): UploadedFileInterface
     {
         $file = new UploadedFile();
 
@@ -82,20 +99,18 @@ class UploadedFileRepository extends EntityRepository implements FileManagerInte
                 ]
             );
 
-        $this->_em->persist($file);
-        $this->_em->flush();
+        $this->entityManager->persist($file);
+        $this->entityManager->flush();
 
-        $this->log(LogLevel::INFO, 'File created', ['file' => $file]);
+        $this->logger->log(LogLevel::INFO, 'File created', ['file' => $file]);
 
         return $file;
     }
 
     /**
-     * @param UploadedFileInterface $original
-     *
-     * @return UploadedFile
+     * {@inheritdoc}
      */
-    public function duplicate(UploadedFileInterface $original)
+    public function duplicate(UploadedFileInterface $original): UploadedFileInterface
     {
         if (!$original->isValid()) {
             throw new InvalidArgumentException('Impossible de dupliquer le fichier ' . $original->getId() . ' car il est invalide !');
@@ -124,26 +139,26 @@ class UploadedFileRepository extends EntityRepository implements FileManagerInte
         $original->copyTo($stream->cast(STREAM_CAST_AS_STREAM));
         $stream->close();
 
-        $this->_em->persist($new);
+        $this->entityManager->persist($new);
 
         return $new;
     }
 
     /**
-     * @param UploadedFileInterface $file
+     * {@inheritdoc}
      */
-    public function delete(UploadedFileInterface $file)
+    public function delete(UploadedFileInterface $file): void
     {
-        $this->_em->remove($file);
-        $this->_em->flush();
+        $this->entityManager->remove($file);
+        $this->entityManager->flush();
 
-        $this->log(LogLevel::INFO, 'File deleted', ['file' => $file]);
+        $this->logger->log(LogLevel::INFO, 'File deleted', ['file' => $file]);
     }
 
     /**
-     * @param string $uuid
+     * {@inheritdoc}
      */
-    public function get($uuid)
+    public function get($uuid): ?UploadedFileInterface
     {
         if (!$uuid) {
             return null;
@@ -152,13 +167,14 @@ class UploadedFileRepository extends EntityRepository implements FileManagerInte
             throw new InvalidArgumentException(sprintf('Identifiant invalide: %s', (string) $uuid));
         }
 
-        return $this->findOneById($uuid);
+        /* @noinspection PhpUndefinedMethodInspection */
+        return $this->repository->findOneById($uuid);
     }
 
     /**
-     * @param UploadedFileInterface $file
+     * {@inheritdoc}
      */
-    public function completed(UploadedFileInterface $file)
+    public function completed(UploadedFileInterface $file): void
     {
         $path = $file->getPath();
         $filesystem = $this->filesystem;
@@ -169,41 +185,29 @@ class UploadedFileRepository extends EntityRepository implements FileManagerInte
             ->setMimeType($filesystem->mimeType($path))
             ->setEtat(UploadedFileInterface::ETAT_ORPHELIN);
 
-        $this->_em->persist($file);
+        $this->entityManager->persist($file);
 
         try {
             $this->eventDispatcher->dispatch(FileUploadEvents::UPLOAD_COMPLETE, new FileUploadCompleteEvent($file));
 
-            $this->_em->flush();
-            $this->log(LogLevel::INFO, 'File completed', ['file' => $file]);
+            $this->entityManager->flush();
+            $this->logger->log(LogLevel::INFO, 'File completed', ['file' => $file]);
         } catch (RejectedFileException $ex) {
             $file->setEtat(UploadedFileInterface::ETAT_REJETE);
 
-            $this->_em->flush();
-            $this->log(LogLevel::WARNING, 'File rejected', ['file' => $file, 'exception' => $ex]);
+            $this->entityManager->flush();
+            $this->logger->log(LogLevel::WARNING, 'File rejected', ['file' => $file, 'exception' => $ex]);
 
             throw $ex;
         }
     }
 
     /**
-     * @param string $level
-     * @param string $message
-     * @param array  $context
-     */
-    protected function log($level, $message, array $context = [])
-    {
-        if (null !== $this->logger) {
-            $this->logger->log($level, $message, $context);
-        }
-    }
-
-    /**
-     * @return array
+     * {@inheritdoc}
      */
-    public function findGarbage()
+    public function findGarbage(): array
     {
-        $files = $this->findBy(['etat' => [UploadedFileInterface::ETAT_EN_COURS, UploadedFileInterface::ETAT_ORPHELIN]]);
+        $files = $this->repository->findBy(['etat' => [UploadedFileInterface::ETAT_EN_COURS, UploadedFileInterface::ETAT_ORPHELIN]]);
 
         $limit = new DateTime('now');
         $limit->modify('- 1 hour');
@@ -219,10 +223,10 @@ class UploadedFileRepository extends EntityRepository implements FileManagerInte
     }
 
     /**
-     * @return array
+     * {@inheritdoc}
      */
-    public function findFilesToValidate()
+    public function findFilesToValidate(): array
     {
-        return $this->findBy(['etat' => [UploadedFileInterface::ETAT_ORPHELIN, UploadedFileInterface::ETAT_NORMAL]]);
+        return $this->repository->findBy(['etat' => [UploadedFileInterface::ETAT_ORPHELIN, UploadedFileInterface::ETAT_NORMAL]]);
     }
 }