DEV Community

Daniyal Javani
Daniyal Javani

Posted on • Edited on

Temporary URL for local driver in Spatie Laravel media library

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',
    ],
],
Enter fullscreen mode Exit fullscreen mode

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');
}
Enter fullscreen mode Exit fullscreen mode

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;
    }
}
Enter fullscreen mode Exit fullscreen mode

Step 4: Create the controller's signed route

Route::get('private-storage/{media}/{filename}', 'ServePrivateStorage')
    ->middleware('signed')
    ->name('private-storage');
Enter fullscreen mode Exit fullscreen mode

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]
        );
    }
}
Enter fullscreen mode Exit fullscreen mode

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,
Enter fullscreen mode Exit fullscreen mode



That's it. Now your local driver does support creating temporary URLs.

Top comments (2)

Collapse
 
gasparotto30 profile image
gasparotto30

Thank you very much!!

Collapse
 
mojtabad profile image
Mojtaba Darvishi

Thank you Daniyal! Very helpful