File uploading is one of the most common features in web applications. In this tutorial, you will learn how to implement file upload with validation in a Laravel 12 application using the Storage facade.
Create a fresh Laravel application if you don't already have one:
composer create-project laravel/laravel file-upload-app
Create a Blade view at resources/views/upload.blade.php with a file input and CSRF token:
<!DOCTYPE html>
<html>
<head><title>File Upload</title></head>
<body>
@if (session('success'))
<p style="color:green">{{ session('success') }}</p>
@endif
@if ($errors->any())
<ul>@foreach ($errors->all() as $e) <li>{{ $e }}</li> @endforeach</ul>
@endif
<form method="POST" action="{{ route('upload.store') }}" enctype="multipart/form-data">
@csrf
<input type="file" name="document" />
<button type="submit">Upload</button>
</form>
</body>
</html>
Generate a Form Request to keep validation logic out of your controller:
php artisan make:request UploadFileRequest
Open app/Http/Requests/UploadFileRequest.php and define the rules:
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class UploadFileRequest extends FormRequest
{
public function authorize(): bool
{
return true;
}
public function rules(): array
{
return [
'document' => [
'required',
'file',
'mimes:pdf,doc,docx,jpg,jpeg,png',
'max:5120', // 5 MB
],
];
}
public function messages(): array
{
return [
'document.required' => 'Please select a file to upload.',
'document.mimes' => 'Only PDF, Word, and image files are allowed.',
'document.max' => 'The file must not exceed 5 MB.',
];
}
}
php artisan make:controller UploadController
Open app/Http/Controllers/UploadController.php and add the upload logic:
namespace App\Http\Controllers;
use App\Http\Requests\UploadFileRequest;
use Illuminate\Http\RedirectResponse;
use Illuminate\View\View;
class UploadController extends Controller
{
public function create(): View
{
return view('upload');
}
public function store(UploadFileRequest $request): RedirectResponse
{
// Store in storage/app/public/uploads — publicly accessible
$path = $request->file('document')->store('uploads', 'public');
return redirect()->route('upload.create')
->with('success', "File uploaded successfully: $path");
}
}
use App\Http\Controllers\UploadController;
Route::get('/upload', [UploadController::class, 'create'])->name('upload.create');
Route::post('/upload', [UploadController::class, 'store'])->name('upload.store');
Run the following command to make uploaded files publicly accessible via the browser:
php artisan storage:link
Files stored in storage/app/public/uploads will be accessible at /storage/uploads/filename.
To display or link to an uploaded file, use the Storage facade:
use Illuminate\Support\Facades\Storage;
// Get the public URL
$url = Storage::url($path); // e.g. /storage/uploads/abc123.pdf
// Check if file exists
Storage::disk('public')->exists('uploads/abc123.pdf');
// Delete a file
Storage::disk('public')->delete('uploads/abc123.pdf');
php artisan serve
Open http://127.0.0.1:8000/upload in your browser and try uploading different file types to test the validation rules.
All Comments