Today’s guide describes the implementation of temporary URL for local driver in spatie/laravel-medialibrary
. We'll accomplish this via Laravel signed URLs.
If you use getTemporaryUrl() function of the laravel-medialibrary
for local driver, you will get the following error:
RuntimeException with message 'This driver does not support creating temporary URLs.'
The below steps describe how to implement getTemporaryUrl function in your Laravel app.
Step 1: Add a private disk to config file
Laravel already comes with local, public and s3 disks and you should add your own disk for private files to config/filesystems
.
/* |-------------------------------------------------------------------------- | Filesystem Disks |-------------------------------------------------------------------------- | | Here you may configure as many filesystem "disks" as you wish, and you | may even configure multiple disks of the same driver. Defaults have | been setup for each driver as an example of the required options. | | Supported Drivers: "local", "ftp", "sftp", "s3", "rackspace" | */ 'disks' => [ 'private' => [ 'driver' => 'local', 'root' => storage_path('app/private'), 'url' => env('APP_URL').'/private-storage', 'visibility' => 'private', ], ],
Step 2: Add files to the private disk
You must ensure that files added to secret-files
collection are automatically added to the private disk.
// in your model public function registerMediaCollections(): void { $this ->addMediaCollection('secret-files') ->useDisk('private'); }
Step 3: Create a controller that handle file requests
It does nothing but returning the media model instance.
Note: You can even authorise using Laravel policy.
namespace App\Http\Controllers; use Illuminate\Http\Request; use Spatie\MediaLibrary\MediaCollections\Models\Media; use Storage; class ServePrivateStorage extends Controller { /** * Handle the incoming request. * * @param \Spatie\MediaLibrary\MediaCollections\Models\Media $media * @return \Illuminate\Http\Response */ public function __invoke(Media $media) { // $this->authorize('view', $media->model); return $media; } }
Step 4: Create the controller's signed route
Route::get('private-storage/{media}/{filename}', 'ServePrivateStorage') ->middleware('signed') ->name('private-storage');
Step 5: Now we need a media URL generator class
In this step we extend the DefaultUrlGenerator
and override the getTemporaryUrl
function.
namespace App\Services; use DateTimeInterface; use Illuminate\Support\Facades\URL; use Spatie\MediaLibrary\Support\UrlGenerator\DefaultUrlGenerator; class MediaUrlGeneratorService extends DefaultUrlGenerator { public function getTemporaryUrl(DateTimeInterface $expiration, array $options = []): string { return URL::temporarySignedRoute( 'private-storage', $expiration, ['media' => $this->media, 'filename' => $this->media] ); } }
Step 6: Replace your URL generator with the default one
Open the config/media-library.php
file and replace the following class with yours.
'url_generator' => Spatie\MediaLibrary\Support\UrlGenerator\DefaultUrlGenerator::class,
That's it. Now your local driver does support creating temporary URLs.
Top comments (2)
Thank you Daniyal! Very helpful
Thank you very much!!