File uploads are a common requirement for many web applications. Whether you’re building a social media platform, an e-commerce site, or a content management system, the ability to handle multiple file uploads efficiently is crucial. Implementing real-time validation for multiple file uploads using Laravel Livewire is a great way to enhance the user experience and ensure that only valid files are processed. In this scenario, we’ll create a Livewire component that allows users to upload multiple files while providing immediate feedback on file validation. However, Invalid files will display validation errors immediately. In this blog post, we’ll explore how to tackle this challenge using Laravel and Livewire, a library that simplifies the process and adds real-time capabilities to your web applications.
Why Use Livewire for Multiple File Uploads?
Before diving into the technical details, let’s briefly discuss why Livewire is an excellent choice for handling multiple file uploads in Laravel.
Livewire is a Laravel package that enables developers to build interactive and dynamic web applications without writing a single line of JavaScript. It seamlessly integrates with Laravel’s existing features, making it an attractive choice for developers familiar with the framework. So, here are some key advantages of using Livewire for file uploads:
- Real-Time Updates: Livewire allows you to create real-time features with minimal effort. You can instantly update the UI as users select and upload files, providing a smoother user experience.
- Server-Side Logic: With Livewire, file uploads are handled on the server side, which simplifies validation, security, and error handling.
- Seamless Integration: Livewire seamlessly integrates with Laravel Blade templates, so you can build interactive file upload components using familiar syntax.
Before moving to the implementation of Livewire Multiple file uploads, let’s quickly take a look at the result we will build.
There will be a Livewire component for uploading multiple files upload.
Also, there will be a validation for multiple file uploads.
I have used a flash message. Hence, on successful upload, there will be a message appearing as a response.
So, let’s begin our journey to implement the Livewire multiple file uploads. However, you will need to follow the below prerequisites before moving ahead.
Prerequisites
Before we start, make sure you have the following prerequisites in place:
- A Laravel development environment set up.
- Basic knowledge of Laravel and Livewire.
Now, let’s dive into the practical aspects of handling multiple file uploads in Laravel with Livewire.
Recommended: Livewire File Upload with Preview: Tips and Best Practices
Step 1 – Setting Up the Laravel Project
Assuming you have a Laravel project ready, ensure you’ve installed Livewire. However, if not, you can install it using Composer.
composer create-project --prefer-dist laravel/laravel livewire-file-upload
After that, you will have to configure the database.
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE={{DATABASE_NAME}}
DB_USERNAME={{DATABASE_USERNAME}}
DB_PASSWORD={{DATABASE_PASSWORD}}
Next, after the database configuration, you will have to install the Livewire library in the Laravel project. So, that you will be able to implement multiple file uploads in Livewire.
Therefore, you will need to install it using the below command.
composer require livewire/livewire
Step 2 – Model and Migration Setup For Multiple File Uploads
In order to save the uploaded file data into the database, you will require a model and migration. Hence, let’s create it.
php artisan make:model File -m
This artisan command will generate a model and a migration respectively. Hence, after having the migration, let’s add a few columns inside that.
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('files', function (Blueprint $table) {
$table->id();
$table->string('file_name');
$table->string('file_name_original');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::dropIfExists('files');
}
};
Also, next, you will have to add a fillable property in the model as per the above columns.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class File extends Model
{
use HasFactory;
protected $fillable = [
'file_name',
'file_name_original'
];
}
After that, you will have to migrate the database using the migrate command.
php artisan migrate
Next, you will require a component in which you will be implementing livewire multiple file uploads. Hence, it can be done by creating a Livewire component.
Recommended: Livewire Pagination in Laravel: Making Your App Dynamic and Responsive
Step 3 – Create Livewire Component For Multiple File Uploads
You can create a livewire component using the below command.
php artisan make:livewire FileUpload
This will generate a component having a class file and a blade file.
After having the component, initially, you will have to design the form. So, that the form will capture the file(s) and send the request to the server.
Step 4 – Design File Upload Component
In order to design the file upload component, simply navigate to the blade file component. After that add the below snippet. Here, this contains a form having a file input.
<div class="container my-5">
<div class="row">
<div class="col-xl-7 m-auto">
{{-- form starts --}}
<form wire:submit.prevent="submitForm">
{{-- Display flash message --}}
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<symbol id="check-circle-fill" fill="currentColor" viewBox="0 0 16 16">
<path
d="M16 8A8 8 0 1 1 0 8a8 8 0 0 1 16 0zm-3.97-3.03a.75.75 0 0 0-1.08.022L7.477 9.417 5.384 7.323a.75.75 0 0 0-1.06 1.06L6.97 11.03a.75.75 0 0 0 1.079-.02l3.992-4.99a.75.75 0 0 0-.01-1.05z" />
</symbol>
<symbol id="info-fill" fill="currentColor" viewBox="0 0 16 16">
<path
d="M8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16zm.93-9.412-1 4.705c-.07.34.029.533.304.533.194 0 .487-.07.686-.246l-.088.416c-.287.346-.92.598-1.465.598-.703 0-1.002-.422-.808-1.319l.738-3.468c.064-.293.006-.399-.287-.47l-.451-.081.082-.381 2.29-.287zM8 5.5a1 1 0 1 1 0-2 1 1 0 0 1 0 2z" />
</symbol>
<symbol id="exclamation-triangle-fill" fill="currentColor" viewBox="0 0 16 16">
<path
d="M8.982 1.566a1.13 1.13 0 0 0-1.96 0L.165 13.233c-.457.778.091 1.767.98 1.767h13.713c.889 0 1.438-.99.98-1.767L8.982 1.566zM8 5c.535 0 .954.462.9.995l-.35 3.507a.552.552 0 0 1-1.1 0L7.1 5.995A.905.905 0 0 1 8 5zm.002 6a1 1 0 1 1 0 2 1 1 0 0 1 0-2z" />
</symbol>
</svg>
{{-- Alert component starts --}}
@if (session()->has('success'))
<div class="alert alert-success alert-dismissible fade show">
<svg class="bi flex-shrink-0 me-2" width="24" height="24" role="img"
aria-label="Success:">
<use xlink:href="#check-circle-fill" />
</svg>
<strong>Success!</strong> {{ session('success') }}
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
@elseif (session()->has('error'))
<div class="alert alert-danger alert-dismissible fade show">
<svg class="bi flex-shrink-0 me-2" width="24" height="24" role="img"
aria-label="Danger:">
<use xlink:href="#exclamation-triangle-fill" />
</svg>
<strong>Alert!</strong> {{ session('error') }}
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
@endif
{{-- Alert component ends --}}
{{-- Card component starts --}}
<div class="card shadow">
<div class="card-header">
<h5 class="card-title fw-bold">Multiple File Uploads Using Livewire </h5>
</div>
<div class="card-body px-5">
{{-- file(s) upload --}}
<div class="form-group my-3">
<label for="files">Files <span class="text-danger">*</span></label>
<input type="file" id="files{{ $random }}" multiple wire:model="files"
aria-describedby="files-error" @error('files.*') aria-invalid="true" @enderror
class="form-control @error('files') is-invalid @enderror">
{{-- Display files validation error message --}}
@error('files.*')
<span id="files-error" class="text-danger">{{ $message }}</span>
@enderror
@error('files')
<span id="files-error" class="text-danger">{{ $message }}</span>
@enderror
</div>
<div class="form-group mb-2">
<button type="submit" class="btn btn-primary">Upload</button>
</div>
</div>
</div>
{{-- Card component ends --}}
</form>
{{-- form ends --}}
</div>
</div>
</div>
Next, you will have to handle file upload functionality in the component class file. Therefore, let’s handle the form submit request to upload files.
Recommended: Building a Dynamic Livewire CRUD Application in Laravel 10
Step 5 – Handle File Upload in Livewire
When you submit the form the request will go to the component class. Hence, you will have to handle it.
<?php
namespace App\Http\Livewire;
use Livewire\Component;
use Livewire\WithFileUploads;
use App\Models\File;
class FileUpload extends Component
{
// use livewire trait
use WithFileUploads;
public $files = [], $random = 0;
public function render()
{
return view('livewire.file-upload');
}
// Define validation rules
protected $rules = [
'files' => 'required',
'files.*' => 'mimes:pdf,csv,xls,xlsx,doc,docx|max:2048'
];
// Define custom validation message
protected $messages = [
'files.required' => 'Please upload a file',
'files.*.mimes' => 'Please upload a valid file (Allowed file pdf, csv, xls, xlsx, doc, docx)',
'files.*.max' => 'The uploaded file size is too large. Max allowed size 2MB',
];
// Realtime file validation for multiple files
public function updatedFiles() {
$this->validate();
}
// Function : Upload Multiple Files
public function submitForm() {
// calling validate function
$this->validate();
$response = [];
foreach($this->files as $file) {
$file->store('documents');
$response[] = File::create([
'file_name' => $file->getFilename(),
'file_name_original' => $file->getClientOriginalName(),
]);
}
$this->random++;
if (count($response) > 0) {
session()->flash('success', count($response). ' File(s) uploaded successfully');
}
else {
session()->flash('error', 'Unable to uploaded file. Please try again');
}
}
}
Next, you will have to render this component in a Laravel blade file. So, the component required a blade file.
Step 6 – Render Livewire Component in Laravel Blade
In order to render the Livewire component you require a Laravel blade file. Hence, let’s create a blade file with the name master.blade.php. We have used Bootstrap classes for applying some basic styles. Hence, the blade file requires Bootstrap CDN.
After creating the file, you will have to render the livewire component. Therefore, let’s add the below snippet inside it.
<!doctype html>
<html lang="en">
<head>
<title>Multiple Files Upload Using Livewire in Laravel 10</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS v5.2.1 -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.1/dist/css/bootstrap.min.css" rel="stylesheet" />
@livewireStyles
</head>
<body>
<main>
@livewire('file-upload')
</main>
<!-- JQuery CDN -->
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js"></script>
@livewireScripts
</body>
</html>
Lastly, you will have to render this blade file in Laravel. Hence, you need a route for this.
Recommended: Livewire Form Validation: Building Better User Experiences in Laravel
Step 7 – Wire up Routes For Multiple Uploads
You have to add a route in web.php for rendering this blade view. Therefore, navigate to the route file and add the below route.
<?php
use Illuminate\Support\Facades\Route;
Route::get('/files', function() {
return view('master');
});
So, it’s done. Now, you are ready to run this application to see the result of Livewire multiple file uploads. Hence, I am wrapping up this post.
Conclusion
As a result, in this tutorial, we’ve covered the process of handling multiple file uploads in Laravel using Livewire. You’ve learned how to create a Livewire component, build a file upload form, handle multiple file uploads, display success messages, and integrate the component into your application. With these steps, you can create dynamic and user-friendly file upload functionality in your Laravel applications, making it easier than ever for users to upload and manage multiple files. Happy coding!
Leave a Reply