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 very much!!
Thank you Daniyal! Very helpful