Laravel file uploads
File Uploads in Laravel
Laravel makes handling file uploads simple by providing convenient methods to manage files in forms, store them in a desired location, and validate them. Here’s a detailed guide on how to handle file uploads in Laravel.
1. Creating the Form for File Upload
The first step is to create a form that allows users to upload a file. In Laravel, the enctype="multipart/form-data"
attribute is essential for file uploads.
Example: Basic File Upload Form in Blade
<form action="{{ route('file.upload') }}" method="POST" enctype="multipart/form-data">
@csrf
<div>
<label for="file">Choose a file:</label>
<input type="file" name="file" id="file">
</div>
<button type="submit">Upload File</button>
</form>
In this example:
@csrf
: This directive adds a CSRF token to the form for security.enctype="multipart/form-data"
: This ensures that file data can be submitted to the server.input type="file"
: This creates a file input field.
2. Handling File Upload in the Controller
Once the form is submitted, you can handle the file upload in the controller. The uploaded file will be available in the request object.
Example: File Upload Handling in the Controller
use Illuminate\Http\Request;
class FileUploadController extends Controller
{
public function uploadFile(Request $request)
{
// Validate the file
$request->validate([
'file' => 'required|mimes:jpg,jpeg,png,pdf|max:2048', // Limit to 2MB and only specific file types
]);
// Check if the file was uploaded
if ($request->hasFile('file')) {
// Get the file
$file = $request->file('file');
// Generate a unique name for the file before saving
$filename = time() . '_' . $file->getClientOriginalName();
// Save the file in the 'uploads' directory within 'storage/app/public'
$filePath = $file->storeAs('uploads', $filename, 'public');
// Return a response or redirect
return back()->with('success', 'File uploaded successfully!')->with('file', $filename);
}
return back()->withErrors('File not uploaded.');
}
}
Here’s how the code works:
$request->validate()
: This validates the uploaded file, ensuring it meets the required constraints (file type, size, etc.).$request->hasFile('file')
: This checks if the file is present in the request.$request->file('file')
: This retrieves the uploaded file object.storeAs()
: This method stores the file in a specific directory with a custom filename. In this case, the file is stored in theuploads
directory insidestorage/app/public
.
3. Configuring Filesystem and Storage
By default, Laravel uses the storage
directory for storing files. To make these files accessible via the web, you need to create a symbolic link between the storage
folder and the public
folder.
Step 1: Creating a Storage Link
Run the following Artisan command to create the symbolic link:
php artisan storage:link
This creates a symbolic link from public/storage
to storage/app/public
, allowing files in storage/app/public
to be accessed from the browser.
Step 2: File Storage Configuration
In the config/filesystems.php
file, you can configure your storage settings. The default disk is usually set to local
:
'disks' => [
'public' => [
'driver' => 'local',
'root' => storage_path('app/public'),
'url' => env('APP_URL') . '/storage',
'visibility' => 'public',
],
],
This configuration ensures that files stored using the public
disk are accessible publicly.
4. Displaying Uploaded Files
Once the file is uploaded, you may want to display or provide a download link to the file.
Example: Displaying the Uploaded File
If you store the file in the public
directory, you can display the file using the URL provided by the storage system:
@if(session('file'))
<div>
<p>File Uploaded: <a href="{{ asset('storage/uploads/' . session('file')) }}" target="_blank">{{ session('file') }}</a></p>
</div>
@endif
asset('storage/uploads/' . session('file'))
: This generates the public URL for the uploaded file.
5. File Validation
When handling file uploads, validation is essential to ensure the uploaded files meet certain criteria, such as file type, size, and more. Laravel provides several validation rules for file uploads:
required
: Ensures that the file input is present.mimes:jpg,jpeg,png,pdf
: Restricts the file type to the specified MIME types.max:2048
: Limits the file size to 2 MB.
Example: File Validation
$request->validate([
'file' => 'required|mimes:jpg,jpeg,png,pdf|max:2048',
]);
This validates that the uploaded file is either a jpg
, jpeg
, png
, or pdf
file and that its size does not exceed 2 MB.
6. File Deletion
To delete a file from the storage, you can use the Storage::delete()
method.
Example: Deleting a File
use Illuminate\Support\Facades\Storage;
if (Storage::exists('public/uploads/' . $filename)) {
Storage::delete('public/uploads/' . $filename);
}
This checks if the file exists in the uploads
directory and deletes it if found.
7. Full Example: File Upload Workflow
Here’s an example of the complete workflow for uploading a file, validating it, storing it, and then displaying the uploaded file.
Step 1: Create the Route
Route::post('/upload', [FileUploadController::class, 'uploadFile'])->name('file.upload');
Step 2: Create the Controller
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
class FileUploadController extends Controller
{
public function uploadFile(Request $request)
{
// Validate file
$request->validate([
'file' => 'required|mimes:jpg,jpeg,png,pdf|max:2048',
]);
// Upload file
if ($request->hasFile('file')) {
$file = $request->file('file');
$filename = time() . '_' . $file->getClientOriginalName();
$filePath = $file->storeAs('uploads', $filename, 'public');
return back()->with('success', 'File uploaded successfully!')->with('file', $filename);
}
return back()->withErrors('File not uploaded.');
}
}
Step 3: Create the Blade View
@if(session('success'))
<div class="alert alert-success">{{ session('success') }}</div>
@endif
<form action="{{ route('file.upload') }}" method="POST" enctype="multipart/form-data">
@csrf
<div>
<label for="file">Choose a file:</label>
<input type="file" name="file" id="file">
</div>
<button type="submit">Upload File</button>
</form>
@if(session('file'))
<div>
<p>File Uploaded: <a href="{{ asset('storage/uploads/' . session('file')) }}" target="_blank">{{ session('file') }}</a></p>
</div>
@endif