Handle Uploads Securely
File uploads are a common vulnerability.
Validation First
$request->validate([
'avatar' => [
'required',
'image',
'mimes:jpeg,png,gif',
'max:2048', // KB
'dimensions:min_width=100,min_height=100,max_width=2000,max_height=2000'
],
'document' => [
'required',
'file',
'mimes:pdf,doc,docx',
'max:10240'
]
]);
Storage
// Public files (avatars, images)
$path = $request->file('avatar')->store('avatars', 'public');
// Stored in storage/app/public/avatars/
// Accessible at /storage/avatars/xxx.jpg
// Private files (documents)
$path = $request->file('document')->store('documents');
// Stored in storage/app/documents/
// Not publicly accessible
Custom Filenames
$filename = Str::uuid() . '.' . $file->extension();
$path = $file->storeAs('avatars', $filename, 'public');
Serving Private Files
Route::get('documents/{document}', function (Document $document) {
abort_unless(auth()->user()->can('view', $document), 403);
return Storage::download($document->path);
});
// Or signed URLs (S3)
return Storage::temporaryUrl($path, now()->addMinutes(5));
Processing Uploads
// Resize images
$image = Image::make($request->file('avatar'));
$image->fit(200, 200);
Storage::put('avatars/small/' . $filename, $image->encode());
// Queue heavy processing
ProcessUpload::dispatch($upload);
Security Checklist
- [ ] Validate file type by content, not just extension
- [ ] Set max file size
- [ ] Generate random filenames
- [ ] Store outside web root when possible
- [ ] Scan for malware (for sensitive apps)
