diff --git a/Command/CheckCommand.php b/Command/CheckCommand.php
new file mode 100644
index 0000000000000000000000000000000000000000..a883bd6b0270c380738992b4976db28496f15e8a
--- /dev/null
+++ b/Command/CheckCommand.php
@@ -0,0 +1,65 @@
+<?php
+
+/*
+ * Copyright (C) 2015 IRSTEA
+ * All rights reserved.
+ */
+
+namespace Irstea\FileUploadBundle\Command;
+
+use Irstea\FileUploadBundle\Model\FileManagerInterface;
+use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
+use Symfony\Component\Console\Helper\ProgressBar;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+
+/**
+ * Description of GarbageCollectorCommand
+ *
+ * @author Guillaume Perréal <guillaume.perreal@irstea.fr>
+ */
+class CheckCommand extends ContainerAwareCommand
+{
+    protected function configure()
+    {
+        $this
+            ->setName('irstea:file-upload:check')
+            ->setDescription("Vérifie l'intégrité des fichiers.")
+        ;
+    }
+
+    protected function execute(InputInterface $input, OutputInterface $output)
+    {
+        /* @var $manager FileManagerInterface */
+        $manager = $this->getContainer()->get('irstea_file_upload.file_manager');
+
+        $em = $this->getContainer()->get('doctrine.orm.entity_manager');
+
+        $files = $manager->findFilesToValidate();
+
+        if(count($files) == 0) {
+            $output->writeln('Aucun fichier à vérifier.');
+            return;
+        }
+
+        $output->writeln('Vérification des fichiers');
+
+        $progress = new ProgressBar($output, count($files));
+        $progress->start();
+
+        foreach($files as $file){
+            $file->validate();
+            if(!$file->isValid()) {
+                $output->writeln(sprintf("\nFichier %s: %s", $file->getEtat(), $file->getPath()));
+                $em->persist($file);
+            }
+            $progress->advance();
+        }
+
+        $progress->finish();
+
+        $em->flush();
+        $output->writeln('');
+    }
+}
diff --git a/Command/CollectGarbageCommand.php b/Command/CollectGarbageCommand.php
new file mode 100644
index 0000000000000000000000000000000000000000..dcab1c3a90d48194434f7d509cf7130f23bb1f89
--- /dev/null
+++ b/Command/CollectGarbageCommand.php
@@ -0,0 +1,63 @@
+<?php
+
+/*
+ * Copyright (C) 2015 IRSTEA
+ * All rights reserved.
+ */
+
+namespace Irstea\FileUploadBundle\Command;
+
+use Irstea\FileUploadBundle\Model\FileManagerInterface;
+use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
+use Symfony\Component\Console\Helper\ProgressBar;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+
+/**
+ * Description of GarbageCollectorCommand
+ *
+ * @author Guillaume Perréal <guillaume.perreal@irstea.fr>
+ */
+class CollectGarbageCommand extends ContainerAwareCommand
+{
+    protected function configure()
+    {
+        $this
+            ->setName('irstea:file-upload:collect-garbage')
+            ->setDescription("Nettoie les fichiers orphelins et partiels.")
+            ->addOption('dry-run', null, InputOption::VALUE_NONE, 'Affiche ce qui devrait être fait, sans le faire')
+        ;
+    }
+
+    protected function execute(InputInterface $input, OutputInterface $output)
+    {
+        /* @var $manager FileManagerInterface */
+        $manager = $this->getContainer()->get('irstea_file_upload.file_manager');
+
+        $files = $manager->findGarbage();
+
+        if(count($files) == 0) {
+            $output->writeln('Aucun fichier à supprimer.');
+            return;
+        }
+
+        if($input->getOption('dry-run')) {
+            $output->writeln(sprintf('%d fichier(s) à supprimer.', count($files)));
+            return;
+        }
+
+        $output->writeln("Suppression des fichiers");
+
+        $progress = new ProgressBar($output, count($files));
+        $progress->start();
+
+        foreach($files as $file){
+            $manager->delete($file);
+            $progress->advance();
+        }
+
+        $progress->finish();
+        $output->writeln('');
+    }
+}
diff --git a/Entity/Repository/UploadedFileRepository.php b/Entity/Repository/UploadedFileRepository.php
index b49e2891c078ccedb0bc426cf6b6d2eb166fd4d3..434ffb6f3ae62d004ad8738cf3fc455361edc9de 100644
--- a/Entity/Repository/UploadedFileRepository.php
+++ b/Entity/Repository/UploadedFileRepository.php
@@ -7,6 +7,7 @@
 
 namespace Irstea\FileUploadBundle\Entity\Repository;
 
+use DateTime;
 use Doctrine\ORM\EntityRepository;
 use Gaufrette\Filesystem;
 use Irstea\FileUploadBundle\Entity\UploadedFile;
@@ -136,4 +137,26 @@ class UploadedFileRepository extends EntityRepository implements FileManagerInte
             $this->logger->log($level, $message, $context);
         }
     }
+
+    public function findGarbage()
+    {
+        $files = $this->findBy(['etat' => [UploadedFileInterface::ETAT_EN_COURS, UploadedFileInterface::ETAT_ORPHELIN]]);
+
+        $limit = new DateTime('now');
+        $limit->modify('- 1 hour');
+
+        return array_filter(
+            $files,
+            function(UploadedFileInterface $file) use($limit) {
+                $mtime = $file->getLastModified();
+                return $mtime === null || $mtime < $limit;
+            }
+        );
+    }
+
+    public function findFilesToValidate()
+    {
+        return $this->findBy(['etat' => [UploadedFileInterface::ETAT_ORPHELIN, UploadedFileInterface::ETAT_NORMAL]]);
+    }
+
 }
diff --git a/Entity/UploadedFile.php b/Entity/UploadedFile.php
index 53b083d524191b071604f0079fbb58c958401563..9002066cebf616d051ca250467d67e10ce6b7cc7 100644
--- a/Entity/UploadedFile.php
+++ b/Entity/UploadedFile.php
@@ -9,9 +9,11 @@ namespace Irstea\FileUploadBundle\Entity;
 
 use DateTime;
 use Doctrine\ORM\Mapping as ORM;
+use Gaufrette\Exception\FileNotFound;
 use Gaufrette\Filesystem;
 use Gaufrette\StreamMode;
 use InvalidArgumentException;
+use Irstea\FileUploadBundle\Entity\Repository\UploadedFileRepository;
 use Irstea\FileUploadBundle\Model\UploadedFileInterface;
 use Irstea\FileUploadBundle\Utils\MimeTypeIcon;
 use Rhumsaa\Uuid\Uuid;
@@ -361,7 +363,7 @@ class UploadedFile implements UploadedFileInterface
 
     public function validate()
     {
-        if (self::ETAT_EN_COURS !== $this->getEtat()) {
+        if (self::ETAT_EN_COURS === $this->getEtat()) {
             return;
         }
 
@@ -403,7 +405,11 @@ class UploadedFile implements UploadedFileInterface
      */
     public function getLastModified()
     {
-        return new \DateTime(sprintf('@%d', $this->filesystem->mtime($this->getPath())));
+        try {
+            return new \DateTime(sprintf('@%d', $this->filesystem->mtime($this->getPath())));
+        } catch(FileNotFound $ex) {
+            return null;
+        }
     }
 
     /** Retourne le contenu du fichier.
diff --git a/Model/FileManagerInterface.php b/Model/FileManagerInterface.php
index 84a4b524fc5e91f05e43537a2885211a7b5d2f39..f2d48cb6cce2b68ad8a2ef063dedfc6fef94cda7 100644
--- a/Model/FileManagerInterface.php
+++ b/Model/FileManagerInterface.php
@@ -37,4 +37,17 @@ interface FileManagerInterface
      * @param UploadedFileInterface $file
      */
     public function completed(UploadedFileInterface $file);
+
+
+    /** Retourne un tableau de fichiers à nettoyer.
+     *
+     * @return UploadedFileInterface[]
+     */
+    public function findGarbage();
+
+    /** Retourne des fichiers à valider.
+     *
+     * @return UploadedFileInterface[]
+     */
+    public function findFilesToValidate();
 }