php 51 lines · 8 steps

Enforcing upload quotas with Laravel middleware

A middleware that blocks file uploads when a team's incoming bytes would exceed its subscription plan's storage quota.

Explained by highlit
1<?php
2 
3namespace App\Http\Middleware;
4 
5use Closure;
6use Illuminate\Http\Request;
7use Symfony\Component\HttpFoundation\Response;
8 
9class EnforceUploadQuota
10{
11 protected array $planLimits = [
12 'free' => 100 * 1024 * 1024,
13 'pro' => 5 * 1024 * 1024 * 1024,
14 'enterprise' => 100 * 1024 * 1024 * 1024,
15 ];
16 
17 public function handle(Request $request, Closure $next): Response
18 {
19 $team = $request->user()->currentTeam;
20 
21 abort_unless($team, 403, 'You must belong to a team to upload files.');
22 
23 $plan = $team->subscription('default')?->stripe_price
24 ? $team->planName()
25 : 'free';
26 
27 $quota = $this->planLimits[$plan] ?? $this->planLimits['free'];
28 
29 $incoming = collect($request->allFiles())
30 ->flatten()
31 ->sum(fn ($file) => $file->getSize());
32 
33 $projected = $team->storage_used + $incoming;
34 
35 if ($projected > $quota) {
36 $remaining = max(0, $quota - $team->storage_used);
37 
38 return response()->json([
39 'message' => "Upload exceeds your {$plan} plan quota.",
40 'quota_bytes' => $quota,
41 'used_bytes' => $team->storage_used,
42 'remaining_bytes' => $remaining,
43 'upgrade_url' => route('billing.plans'),
44 ], Response::HTTP_PAYMENT_REQUIRED);
45 }
46 
47 $request->attributes->set('upload_bytes', $incoming);
48 
49 return $next($request);
50 }
51}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Middleware is the right place to reject requests before controllers run wasteful work.
  2. 2Summing incoming file sizes against a known limit lets you fail fast with a precise, actionable error.
  3. 3Passing computed data downstream via request attributes avoids recomputing it in the controller.

Related explainers

Share this explainer

Here's the card — post it anywhere.

Enforcing upload quotas with Laravel middleware — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code