dustin10 / VichUploaderBundle

A simple Symfony bundle to ease file uploads with ORM entities and ODM documents.
MIT License
1.83k stars 519 forks source link

Add possibility to specify upload directory when using storage #1377

Open mysterty opened 1 year ago

mysterty commented 1 year ago

Feature Request

Q A
New Feature yes
RFC yes
BC Break no

Summary

Actually, using storage like flysystem, you need to make one storage configuration by mapping (+ one "default" for imagine if you use it) :

oneup_flysystem:
  adapters:
    default_adapter:
      local:
        location: "%kernel.project_dir%/public/"
    media_adapter:
      local:
        location: "%kernel.project_dir%/public/uploads/medias/"
    image_adapter:
      local:
        location: "%kernel.project_dir%/public/uploads/images/"
    user_picture_adapter:
      local:
        location: "%kernel.project_dir%/public/uploads/user_pictures/"
  filesystems:
    default_filesystem:
      adapter: default_adapter
      alias: League\Flysystem\Filesystem
      mount: default_filesystem
    media_filesystem:
      adapter: aws_adapter
      alias: League\Flysystem\Filesystem
      mount: media_filesystem
    image_filesystem:
      adapter: images_adapter
      alias: League\Flysystem\Filesystem
      mount: image_filesystem

vich_uploader:
  db_driver: orm
  storage: flysystem

  mappings:
    media:
      uri_prefix: "/uploads/medias"
      upload_destination: oneup_flysystem.media_filesystem_filesystem
    image:
      uri_prefix: "/uploads/images"
      upload_destination: oneup_flysystem.image_filesystem_filesystem
    user_picture:
      uri_prefix: "/uploads/user_pictures"
      upload_destination: oneup_flysystem.user_picture_filesystem_filesystem

liip_imagine:

  loaders:
    flysystem_loader:
      flysystem:
        filesystem_service: oneup_flysystem.default_filesystem_filesystem

  # default loader to use for all filter sets
  data_loader: flysystem_loader

I propose to directly use uri_prefix as directory destination or add an optional directory_destination like :

oneup_flysystem:
  adapters:
    default_adapter:
      local:
        location: "%kernel.project_dir%/public/"
  filesystems:
    default_filesystem:
      adapter: default_adapter
      alias: League\Flysystem\Filesystem
      mount: default_filesystem

vich_uploader:
  db_driver: orm
  storage: flysystem

  mappings:
    media:
      uri_prefix: "/uploads/medias"
      upload_destination: oneup_flysystem.default_filesystem_filesystem
      upload_directory: "/uploads/medias/"
    image:
      uri_prefix: "/uploads/images"
      upload_destination: oneup_flysystem.default_filesystem_filesystem
      upload_directory: "/uploads/images/"
    user_picture:
      uri_prefix: "/uploads/user_pictures"
      upload_destination: oneup_flysystem.default_filesystem_filesystem
      upload_directory: "/uploads/user_pictures/"

liip_imagine:

  loaders:
    flysystem_loader:
      flysystem:
        filesystem_service: oneup_flysystem.default_filesystem_filesystem

  # default loader to use for all filter sets
  data_loader: flysystem_loader
mysterty commented 1 year ago

Note : this can be accomplished with custom directory namer, and it can also be more friendly used in addition with liip imagine :

vich_uploader:
  db_driver: orm
  storage: flysystem

  mappings:
    media:
      uri_prefix:  "/uploads/.."
      upload_destination: oneup_flysystem.default_filesystem_filesystem ## oneup FlySystem
      namer: Vich\UploaderBundle\Naming\SmartUniqueNamer
      directory_namer:
        service: vich_uploader.namer_directory_property
        options: { property: "directory", transliterate: false }
// Entity\Media.php
class Media
{
    private ?string $basePath = '/uploads/medias/';
    private ?string $directory = null;
    [...]
    // ##################### Custom methods #####################

    public function getDirectory(): ?string
    {
        $date = $this->createdAt?$this->createdAt:date('Y-m-d H:i:s');
        return $this->basePath.$date->format("Y").'/'.$date->format("m").'/';
    }

    public function getUrl(): ?string
    {
        return sprintf('%s/%s', $this->getDirectory(), $this->filename);
    }
    [...]
}

Yet, it could be for some uses...