Laravel: Display Images With Temporary URLs


I was messing around with Rackspace’s Cloud Files and discovered that creating temporary URLs to my images is not only a bit of a pain, but it’s also very slow. I needed another way and Spatie’s laravel-url-signer was just the thing. We’ll also be using Intervention Image to serve the image.

Install Laravel URL Signer and Intervention Image

composer require spatie/laravel-url-signer

Then

composer require intervention/image

Register the ServiceProviders and Façades

Open config/app.php and paste the following in their respective locations.


'providers' => [
    ...
    Spatie\UrlSigner\Laravel\UrlSignerServiceProvider::class,
    Intervention\Image\ImageServiceProvider::class,
];

'aliases' => [
    ...
    'UrlSigner' => Spatie\UrlSigner\Laravel\UrlSignerFacade::class,
    'Image' => Intervention\Image\Facades\Image::class,
];

Create Routes

Next we’ll need to create a route to generate the temporary URL, passing the name of the file we want to view as a URL parameter. We’ll store our image in storage/app/public.

Put an image named file.jpg (or whatever your filename is) into storage/app/public.

Next we need a route for getting the image; we’re going to pass the image name as part of the URL string and work some magic in our controller. Add the following to your routes file.

Route::get('get/{filename}', [email protected]')->where('filename', '^[^/]+$');

Next we need to create a route to make sure the URL is valid (not expired) and, if valid, return the image. Using middleware we can also make sure the user is logged in by putting auth into the middleware array (['signedurl', 'auth']). For now we’ll just leave it so anyone can view the file.

Note that we’re using the Intervention Image library to return the image.

Route::get('file/{filename}', ['middleware' => ['signedurl'], function ($filename) {
    return Image::make(storage_path('app/public/'.$filename))->response();
}]);

Create a Controller

Next we’ll create a controller with the method to generate the temporary link and then serve our image in a view.

php artisan make:controller FilesController

Add the signer() method to the FilesController

// Note that, in this instance our URL is only good for 10 seconds because we're setting a timestamp with Carbon.

public function signer($filename)
{
    $url = UrlSigner::sign(url('file/'.$filename), Carbon::now()->addSeconds(10));
    return view('file', compact('url'));
}

Don’t forget to import UrlSigner and Carbon into FilesController!

use UrlSigner;
use Carbon\Carbon;

Create a View

Create a new view and name it file.blade.php and add the following code.

<img src="{{$url}}" alt="">

View the Image

Now retrieve the image with the URL structure http://appname.dev/get/filename.jpg