Closed ibvodafoneziggo closed 1 year ago
When passing visibility('private')
, Filament generates temporary URLs on the server side, is that not happening for you?
It does generate the temporary URL, but the base url of that URL is still the inaccessible S3 url.
In the AWSS3 Adapter of Laravel I see this code for the temporary : https://github.com/laravel/framework/blob/cee91ab69478ab8a23b7ed2467a188bbbdb6f51b/src/Illuminate/Filesystem/AwsS3V3Adapter.php#L77C28-L77C28
I'll try to set the temporary_url to my own host to have url's generated as a proxy. If I'm correc this is the function that Filament uses if the driver is set to S3 (https://github.com/filamentphp/filament/blob/9d347a3a9a4dfba832de0b1f4fd2677280ec6c99/packages/forms/src/Components/BaseFileUpload.php#L125C34-L125C34).
Adding a temporary_url
config to S3 doesn't work, it's still using the AWS_URL/AWS_ENDPOINT to generate the URL.
Livewire docs are mentioning this however (something that breaks what I'm trying to achieve): If you've configured Livewire to use S3 for temporary file storage, calling ->temporaryUrl() will generate a temporary, signed URL from S3 directly so that you don't hit your Laravel app server for this preview at all. (https://laravel-livewire.com/docs/2.x/file-uploads#preview-urls)
You can override getUploadedFileUsing()
if you want, I don't think this is something that Filament can blanket fix for all people? We are generating temporary URLs using Laravel's own temporaryUrl()
method.
As above, I don't think there is a fix on the Filament side, we are just leaning on the existing file upload features of Livewire
Heya @ibvodafoneziggo
Hit the same issue today - We use minio purely as a proxied data store because it's easier than keeping volumes in k8s over multiple pods during deploys.
It's a very simple fix using the spaite media library plugin with the file uploads.
Force Livewire to use the local disk for temp uploads in config/livewire.php
return [
'legacy_model_binding' => false,
'temporary_file_upload' => [
'disk' => 'local'
],
];
in config/media-library.php
you'll want to override the Url generator
'url_generator' => \App\MediaLibrary\PrivateUrlGenerator::class,
Create the private url generator, that just returns a signed route
class PrivateUrlGenerator extends DefaultUrlGenerator
{
public function getUrl(): string
{
return URL::signedRoute('download-media', ['media' => $this->media->id]);
}
}
From that route, return the media
Route::get('/download-media/{media}', function (Media $media) {
return $media;
})
->name('download-media')
->middleware('signed');
Media will be proxied via Laravel app now. Copy the same for the filament upload fields and you will be golden.
Hi @nicko170, thanks for the neat solution! We went a little different route and opened up a public route on the S3 bucket. We then created a custom component that would retrieve the file via the public route.
Heya @ibvodafoneziggo
Hit the same issue today - We use minio purely as a proxied data store because it's easier than keeping volumes in k8s over multiple pods during deploys.
It's a very simple fix using the spaite media library plugin with the file uploads.
Force Livewire to use the local disk for temp uploads in
config/livewire.php
return [ 'legacy_model_binding' => false, 'temporary_file_upload' => [ 'disk' => 'local' ], ];
in
config/media-library.php
you'll want to override the Url generator'url_generator' => \App\MediaLibrary\PrivateUrlGenerator::class,
Create the private url generator, that just returns a signed route
class PrivateUrlGenerator extends DefaultUrlGenerator { public function getUrl(): string { return URL::signedRoute('download-media', ['media' => $this->media->id]); } }
From that route, return the media
Route::get('/download-media/{media}', function (Media $media) { return $media; }) ->name('download-media') ->middleware('signed');
Media will be proxied via Laravel app now. Copy the same for the filament upload fields and you will be golden.
this is a good solution to problem but want to improve this solution :
use Spatie\MediaLibrary\Support\UrlGenerator\DefaultUrlGenerator;
class PrivateS3UrlGenerator extends DefaultUrlGenerator
{
public function getUrl(): string
{
if ($this->getDiskName() === 's3-private') {// s3 private for your private s3 bucket intended to have temp url.
return $this->getTemporaryUrl(now()->addMinutes(5));
}
return parent::getUrl();// or any other disks goes to get link directly.
}
}
Package
filament/forms
Package Version
2.17.53
Laravel Version
10.28.0
Livewire Version
2.12.6
PHP Version
8.2
Problem description
I'm uploading a file to S3 storage that is only accessible by my server, not to the client. When I'm uploading a file it works perfectly and the file is put in the S3 bucket. When previewing the file though, the frontend tries to read the S3 bucket itself, which only the server has access to.
Forms\Components\FileUpload::make('attachments') ->disk(config('storage.driver')) ->directory(config('storage.attachements-directory')) ->visibility(config('storage.storage-bucket-visibility')) ->maxSize(config('storage.max-upload-size')) ->maxFiles(config('storage.max-file-amount')) ->enableDownload() ->multiple()
This is the configuration I'm using, where the disk is an S3 bucket and the visibility is set to private. The URL that the frontend is trying to read is the disk configuration url.
Expected behavior
I'm expecting the server to act as a proxy to retrieve the file and serve it to the client, but that doesn't seem to be configurable.
Steps to reproduce
Reproduction repository
https://github.com/ibvodafoneziggo/filament-uploadfile-issue-example
Relevant log output
No response