fsi-open / files

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Storing Private Files

pawloaka opened this issue · comments

My fsi_files.yaml looks like:

fsi_files:
    url_adapters:
        public: 'fsi_files.url_adapter.public'
        private: 'fsi_files.url_adapter.private'
    entities:
        App\User:
            filesystem: 'private'
            prefix: user
            fields:
                - { name: profile }

oneup_flysystem.yaml looks like:

oneup_flysystem:
    adapters:
        public_adapter:
            local:
                directory: '%kernel.project_dir%/public/uploads'
        private_adapter:
            local:
                directory: '%kernel.project_dir%/var/uploads'
    filesystems:
        public_filesystem:
            adapter: public_adapter
            mount: public_filesystem
        private_filesystem:
            adapter: private_adapter
            mount: private_filesystem

services.yaml looks like:

...
  fsi_files.url_adapter.public:
    class: FSi\Component\Files\UrlAdapter\BaseUrlAdapter
    arguments:
      $uriFactory: '@Psr\Http\Message\UriFactoryInterface'
      $baseUrl: 'https://localhost/uploads/'

  fsi_files.url_adapter.private:
    class: FSi\Component\Files\UrlAdapter\BaseUrlAdapter
    arguments:
      $uriFactory: '@Psr\Http\Message\UriFactoryInterface'
      $baseUrl: 'https://localhost/private/uploads/'
...

And now my question is how to access from the web these private files stored in %kernel.project_dir%/var/uploads?
Should I make a special controller which is listening on https://localhost/private/uploads/? If yes, how it should look like?

Hello,
Yes, you will need a dedicated controller for private files, which would look something like this:

declare(strict_types=1);

namespace Your\NamespacePath;

use finfo; // using this requires the `ext-fileinfo` extension, so make sure you have it
use FSi\Component\Files\FileManager;
use FSi\Component\Files\WebFile;
use Zend\Diactoros\CallbackStream;
use Zend\Diactoros\Response;
use const FILEINFO_MIME_TYPE;

final class PrivateFileController
{
    private FileManager $fileManager;

    public function __construct(FileManager $fileManager)
    {
        $this->fileManager = $fileManager;
    }

    public function __invoke()
    {
        $file = $this->fetchPrivateFile();
        $fileName = $this->fileManager->filename($file);
        $content = $this->fileManager->contents($file);
        // or however else you want to read the MIME type
        $mimeType = (new finfo(FILEINFO_MIME_TYPE))->buffer($content);

        $response = new Response(
            new CallbackStream(fn(): string => $content)
        );
        $response = $response->withHeader('Content-Type', $mimeType ?: 'application/octet-stream');
        $response = $this->setContentDisposition($response, 'inline', $fileName);

        return $response;
    }

    private function fetchPrivateFile(): WebFile
    {
        // retrieve the file from the entity it is assigned to
    }
}

I basically copied this from one of our projects (we use PSR-7 complaint requests/response but I am sure you can make it work with Symfony's classes), but all you need is to basically read the contents of the file and have a response that will properly return it.

Awesome, thanks 👍🏻