php
41 lines · 6 steps
Time-limited signed download links in Laravel
A controller that hands out expiring, tamper-proof URLs and streams the file only when the signature checks out.
Explained by
highlit
1<?php
2
3namespace App\Http\Controllers;
4
5use App\Models\Document;
6use Illuminate\Http\Request;
7use Illuminate\Support\Facades\Storage;
8use Illuminate\Support\Facades\URL;
9use Symfony\Component\HttpFoundation\StreamedResponse;
10
11class DocumentDownloadController extends Controller
12{
13 public function generate(Request $request, Document $document)
14 {
15 $this->authorize('download', $document);
16
17 $url = URL::temporarySignedRoute(
18 'documents.download',
19 now()->addMinutes(15),
20 ['document' => $document->id]
21 );
22
23 return response()->json([
24 'download_url' => $url,
25 'expires_at' => now()->addMinutes(15)->toIso8601String(),
26 ]);
27 }
28
29 public function download(Request $request, Document $document): StreamedResponse
30 {
31 abort_unless($request->hasValidSignature(), 403, 'This download link has expired.');
32
33 $disk = Storage::disk($document->disk);
34
35 abort_unless($disk->exists($document->path), 404);
36
37 return $disk->download($document->path, $document->original_name, [
38 'Content-Type' => $document->mime_type,
39 ]);
40 }
41}
01 / 01
STEP 01
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1Signed URLs let you delegate access without exposing storage paths or requiring a session on the download itself.
- 2Splitting link generation from the actual download keeps authorization and delivery as separate, verifiable steps.
- 3Streaming through the Storage facade avoids loading the whole file into memory and works across local and cloud disks.
Related explainers
php
<?php class NameParser {
Parsing a full name into components in PHP
string-parsing
arrays
normalization
Intermediate
8 steps
php
<?php namespace App\Services\Checkout;
Validating coupons with Laravel's Pipeline
pipeline
chain of responsibility
transactions
Intermediate
7 steps
php
<?php namespace App\Services;
How a password strength validator works in PHP
validation
regular-expressions
data-driven
Intermediate
8 steps
php
<?php namespace App\Services;
Building a cached daily leaderboard in Laravel
caching
aggregation
eager-loading
Intermediate
9 steps
php
<?php final class RotatingFileLogger {
How a rotating file logger works in PHP
logging
file-rotation
io
Intermediate
9 steps
go
package middleware import ( "net/http"
Per-plan export limits in Gin middleware
middleware
rate-limiting
authorization
Intermediate
7 steps
Share this explainer
Here's the card — post it anywhere.
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code
Embed this explainer
Drop the interactive walkthrough into a blog or docs. Views never cost a credit.
<iframe src="https://highlit.co/explainers/time-limited-signed-download-links-in-laravel-explained-php-74e6/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.