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 👍🏻