diff --git a/config/packages/vich_uploader.yaml b/config/packages/vich_uploader.yaml
index 6d5709c7dd7b26f8aa456b72ca0ae73c3755c4a8..dcf635fa71a3f3e759b0a29619d60528b1931fe3 100755
--- a/config/packages/vich_uploader.yaml
+++ b/config/packages/vich_uploader.yaml
@@ -4,31 +4,5 @@ vich_uploader:
         default_file:
             upload_destination: '%kernel.root_dir%/../web'
             directory_namer: App\Services\UploadDirectoryNamer
-            namer: vich_uploader.namer_origname
-        import_file:
-            upload_destination: '%kernel.root_dir%/../web'
-            directory_namer: App\Services\UploadDirectoryNamer
-        image:
-            upload_destination: '%kernel.root_dir%/../web'
-            # inject_on_load: true
-            directory_namer: App\Services\UploadDirectoryNamer
-            namer: vich_uploader.namer_origname
-        element_image:
-            upload_destination: '%kernel.root_dir%/../web'
-            directory_namer: App\Services\UploadDirectoryNamer
-            namer: vich_uploader.namer_origname
-            delete_on_remove: true
-        element_file:
-            upload_destination: '%kernel.root_dir%/../web'
-            directory_namer: App\Services\UploadDirectoryNamer
-            namer: vich_uploader.namer_origname
-            delete_on_remove: true
-        partner_image:
-            upload_destination: '%kernel.root_dir%/../web'
-            directory_namer: App\Services\UploadDirectoryNamer
-            namer: ~
-        config_image:
-            upload_destination: '%kernel.root_dir%/../web'
-            directory_namer: App\Services\UploadDirectoryNamer
-            namer: ~
+            namer: App\Services\UploadFileNamer    
         # if you add new image class, don't forget to add the relevant service in services_admin.yml
\ No newline at end of file
diff --git a/config/services.yaml b/config/services.yaml
index f312cd9eef718ee7e5433e3ca8c2d13f7709d89d..6e85e3dfd0a3df768155f501137640f940df787c 100755
--- a/config/services.yaml
+++ b/config/services.yaml
@@ -35,6 +35,11 @@ services:
       public: true
       arguments: []
 
+    App\Services\UploadFileNamer:
+      class: App\Services\UploadFileNamer
+      public: true
+      arguments: []
+
     App\Services\AsyncService:
       arguments:
         $rootDir: '%kernel.root_dir%'
@@ -167,6 +172,13 @@ services:
         tags:
             - { name: sonata.admin, manager_type: doctrine_mongodb, group: "contents", label: abouts._label }
 
+    admin.files:
+        class: App\Admin\FileAdmin
+        arguments: [~, App\Document\File, '']
+        calls: [ [ setGoGoTranslator, ['@translator'] ] ]
+        tags:
+            - { name: sonata.admin, manager_type: doctrine_mongodb, group: "contents", label: files._label }
+
 
     # --------- CONFIGURATION -----------
 
diff --git a/src/Admin/FileAdmin.php b/src/Admin/FileAdmin.php
new file mode 100644
index 0000000000000000000000000000000000000000..059e75dc51eadc379d595f22c5ed5920cdfafc3c
--- /dev/null
+++ b/src/Admin/FileAdmin.php
@@ -0,0 +1,44 @@
+<?php
+
+namespace App\Admin;
+
+use Sonata\AdminBundle\Datagrid\DatagridMapper;
+use Sonata\AdminBundle\Datagrid\ListMapper;
+use Sonata\AdminBundle\Form\FormMapper;
+use Symfony\Component\Form\Extension\Core\Type\FileType;
+
+class FileAdmin extends GoGoAbstractAdmin
+{
+    protected $datagridValues = [
+        '_page' => 1,
+        '_sort_order' => 'DESC',
+        '_sort_by' => 'updatedAt',
+    ];
+
+    protected function configureFormFields(FormMapper $formMapper)
+    {
+        $disable = $this->getSubject()->getId();
+        $formMapper
+            ->add('file', FileType::class)
+            ->add('fileName', null, ['disabled' => $disable])
+            ->add('customDirectory', null, ['disabled' => $disable])
+            ;
+    }
+
+    protected function configureDatagridFilters(DatagridMapper $datagridMapper)
+    {
+        $datagridMapper->add('fileName');
+    }
+
+    protected function configureListFields(ListMapper $listMapper)
+    {
+        $listMapper
+            ->addIdentifier('fileName')
+            ->add('fileUrl')
+            ->add('_action', 'actions', [
+                'actions' => [
+                    'delete' => [],
+                ],
+            ]);
+    }
+}
diff --git a/src/Document/AbstractFile.php b/src/Document/AbstractFile.php
index 489be30b3769cd66da75932101410bad48fb5cb2..b22d1d48b394953efeed9647bb03dbbb92514ef9 100755
--- a/src/Document/AbstractFile.php
+++ b/src/Document/AbstractFile.php
@@ -6,6 +6,7 @@ use App\Services\UploadDirectoryNamer;
 use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB;
 use Symfony\Component\HttpFoundation\File\UploadedFile;
 use Vich\UploaderBundle\Mapping\Annotation as Vich;
+use Vich\UploaderBundle\Mapping\PropertyMapping;
 
 /**
  * Represent a common File. Need to be extended by real Document
@@ -44,7 +45,7 @@ class AbstractFile implements \Serializable
 
     public function __toString()
     {
-        return $this->getFileUrl();
+        return $this->getFileName();
     }
 
     /**
@@ -129,7 +130,7 @@ class AbstractFile implements \Serializable
         global $kernel;
         $container = $kernel->getContainer();
         $uploadDirHelper = $container->get(UploadDirectoryNamer::class);
-        $filePath = $uploadDirHelper->getDirectoryPathFromKey($this->vichUploadFileKey).'/'.$this->fileName;
+        $filePath = $uploadDirHelper->getDirectoryPath($this).'/'.$this->fileName;
         if ($suffix) {
             return preg_replace(
                 '/(\.jpe?g|\.png)$/',
@@ -156,6 +157,11 @@ class AbstractFile implements \Serializable
         return $url;
     }
 
+    public function getCustomDirectory()
+    {
+        return '';
+    }
+
     public function getFile()
     {
         return $this->file;
diff --git a/src/Document/EmbeddedImage.php b/src/Document/EmbeddedImage.php
index 408f7d37d968057f9579b077aedd3abb471677a8..e90bc1b3445d8433e4a9fe3ea79e66f0c8127815 100755
--- a/src/Document/EmbeddedImage.php
+++ b/src/Document/EmbeddedImage.php
@@ -22,7 +22,7 @@ class EmbeddedImage extends AbstractFile
 
     public function __toString()
     {
-        return $this->getImageUrl();
+        return $this->isExternalFile() ? $this->getExternalImageUrl() : $this->getFileName();
     }
 
     public function toJson()
diff --git a/src/Document/File.php b/src/Document/File.php
new file mode 100755
index 0000000000000000000000000000000000000000..b856afb09c84e2ba51c356f306f8556537e2024b
--- /dev/null
+++ b/src/Document/File.php
@@ -0,0 +1,62 @@
+<?php
+
+namespace App\Document;
+
+use Doctrine\ODM\MongoDB\Mapping\Annotations as MongoDB;
+use Vich\UploaderBundle\Mapping\Annotation as Vich;
+
+/**
+ * @MongoDB\Document
+ * @Vich\Uploadable
+ */
+class File extends AbstractFile
+{
+    /**
+     * @var int
+     *
+     * @MongoDB\Id(strategy="INCREMENT")
+     */
+    private $id;
+
+    /** @MongoDB\Field(type="string") */
+    private $customDirectory = '';
+
+    protected $vichUploadFileKey = 'general_file';
+
+    /**
+     * Get the value of customDirectory
+     */ 
+    public function getCustomDirectory()
+    {
+        return $this->customDirectory;
+    }
+
+    public function setFileName($fileName)
+    {
+        // Prevent resetting fileName to null, so we can edit the file without changing fileName
+        if ($fileName) $this->fileName = $fileName;
+        return $this;
+    }
+
+    /**
+     * Set the value of customDirectory
+     *
+     * @return  self
+     */ 
+    public function setCustomDirectory($customDirectory)
+    {
+        $this->customDirectory = $customDirectory;
+
+        return $this;
+    }
+
+    /**
+     * Get the value of id
+     *
+     * @return  int
+     */ 
+    public function getId()
+    {
+        return $this->id;
+    }
+}
diff --git a/src/Services/UploadDirectoryNamer.php b/src/Services/UploadDirectoryNamer.php
index 000c882dbb31fd5135c9480265cfccd7f3193106..38ad63fec28c72d0ce7f420001f6f34e6ae28505 100755
--- a/src/Services/UploadDirectoryNamer.php
+++ b/src/Services/UploadDirectoryNamer.php
@@ -22,6 +22,7 @@ class UploadDirectoryNamer implements DirectoryNamerInterface
       'partner_image' => '/images/partners',
       'config_image' => '/images/config',
       'import_file' => '/imports',
+      'general_file' => '/files',
       'default_file' => '/default',
     ];
 
@@ -32,13 +33,13 @@ class UploadDirectoryNamer implements DirectoryNamerInterface
 
     public function directoryName($object, PropertyMapping $mapping): string
     {
-        $name = $this->getDirectoryPathFromKey($object->getVichUploadFileKey());
-
-        return $name;
+        return $this->getDirectoryPath($object);
     }
 
-    public function getDirectoryPathFromKey($key)
+    public function getDirectoryPath($object)
     {
-        return $this->BASE_PATH . $this->dmFactory->getCurrentDbName() . $this->PATHS[$key];
+        $path = $this->BASE_PATH . $this->dmFactory->getCurrentDbName() . $this->PATHS[$object->getVichUploadFileKey()];
+        $path .= $object->getCustomDirectory();
+        return $path;
     }
 }
diff --git a/src/Services/UploadFileNamer.php b/src/Services/UploadFileNamer.php
new file mode 100755
index 0000000000000000000000000000000000000000..840968977dee6040b41bdaac2393cf6e193d85d0
--- /dev/null
+++ b/src/Services/UploadFileNamer.php
@@ -0,0 +1,27 @@
+<?php
+
+namespace App\Services;
+
+use Vich\UploaderBundle\Mapping\PropertyMapping;
+use Vich\UploaderBundle\Naming\NamerInterface;
+use Vich\UploaderBundle\Util\Transliterator;
+
+/**
+ * Directory namer wich can create subfolder depends on generated filename.
+ *
+ * @author Konstantin Myakshin <koc-dp@yandex.ru>
+ */
+class UploadFileNamer implements NamerInterface
+{    
+    public function name($object, PropertyMapping $mapping): string
+    {
+        if ($object->getFileName()) return $object->getFileName();
+        
+        $file = $mapping->getFile($object);
+        $name = $file->getClientOriginalName();
+
+        $name = Transliterator::transliterate($name);
+
+        return $name;
+    }
+}
diff --git a/translations/admin+intl-icu.fr.yaml b/translations/admin+intl-icu.fr.yaml
index 92ee1edefe48a25dea59d31554efa6a6fbf9bbb6..0ec1f1dd2db506c7a9a7c93084d5d0d8bbbf562e 100755
--- a/translations/admin+intl-icu.fr.yaml
+++ b/translations/admin+intl-icu.fr.yaml
@@ -643,6 +643,19 @@ duplicates:
     merge: "Fusionnez les doublons"
     wantMore: "J'en veux encore ! (Plus que {count} doublons à traiter)"
 
+files:
+  _label: Uploader des fichiers
+  fields:
+    file: Fichier
+    fileName: Nom du fichier
+    fileUrl: Url
+  form:
+    fileName: Changer le nom du fichier (optionel)
+    fileName_placeholder: "nouveau_nom.png"
+    customDirectory: Changer le répertoire d'upload
+    customDirectory_help: Dans certains cas, par l'exemple pour l'upload d'une police d'icones, vous devez respecter une arborescence de fichier précise (le fichier CSS à la racine, et les fichiers polices dans un répertoire fonts par exemple)
+    customDirectory_placeholder: "/fonts"
+
 categories:
   _label: "Catégories"
   list: