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}', 'FilesController@signer')->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