how to make asychronous multiple upload files with progress bar in laravel?
To create an asynchronous multiple file upload with a progress bar in Laravel, you can use a combination of technologies such as jQuery, AJAX, Laravel Echo, and Vue.js. Here's a step-by-step guide to help you achieve this:
- Install Laravel Echo and Vue.js First, you need to install Laravel Echo and Vue.js in your Laravel project. You can install Laravel Echo using composer:
composer require laravel-echo
Next, you need to install Vue.js using npm:
npm install vue
- Configure Laravel Echo
After installing Laravel Echo and Vue.js, you need to configure Laravel Echo in your
app.js
file:
import Echo from 'laravel-echo';
window.Echo = new Echo({
broadcaster: 'pusher',
key: process.env.MIX_PUSHER_APP_KEY,
cluster: process.env.MIX_PUSHER_APP_CLUSTER,
forceTLS: true
});
- Create a Vue.js component
Next, you need to create a Vue.js component to handle the file uploads and progress bar. Create a new file called
UploadComponent.vue
in theresources/js/components
directory and add the following code:
<template>
<div>
<input type="file" multiple ref="files" @change="handleFilesUpload">
<ul>
<li v-for="file in files" :key="file.name">
<progress :value="file.progress" max="100"></progress>
<span>{{ file.name }}</span>
</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
files: []
};
},
methods: {
handleFilesUpload() {
this.files = [];
const files = this.$refs.files.files;
for (const file of files) {
this.files.push({
name: file.name,
progress: 0
});
const reader = new FileReader();
reader.onload = (event) => {
const fileData = event.target.result;
axios.post('/upload', { file: fileData })
.then(response => {
this.$set(this.files.find(f => f.name === file.name), 'progress', 100);
console.log(response.data);
})
.catch(error => {
console.error(error);
});
};
reader.readAsDataURL(file);
}
}
}
}
</script>
This component uses Vue.js to handle the file uploads and progress bar. It listens for the change
event on the file input and creates a new FileReader
instance for each file. When the file is read as a data URL, it sends an AJAX request to the /upload
route with the file data. Once the file is uploaded, the progress bar is updated to 100%.
- Create a Laravel route and controller
Next, you need to create a Laravel route and controller to handle the file uploads. Create a new route in
routes/web.php
:
Route::post('/upload', 'UploadController@store');
Create a new controller called UploadController.php
in the app/Http/Controllers
directory and add the following code:
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
class UploadController extends Controller
{
public function store(Request $request)
{
$file = $request->file('file');
$filename = time() . '-' . $file->getClientOriginalName();
$path = Storage::disk('public')->putFileAs('uploads', $file, $filename);
event(new FileUploaded($path));
return response()->json(['path' => $path]);
}
}
This controller uses Laravel's Storage
facade to save the uploaded file to disk and broadcast an event using Laravel Echo.
- Create a Laravel event
Finally, you need to create a Laravel event to broadcast the file upload event to the client. Create a new file called
app/Events/FileUploaded.php
and add the following code:
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class FileUploaded
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $path;
/**
* Create a new event instance.
*
* @param string $path
* @return void
*/
public function __construct($path)
{
$this->path = $path;
}
/**
* Broadcast the event to the App\Events\FileUploaded channel.
*
* @return array
*/
public function broadcastOn()
{
return ['app'];
}
}
This event uses Laravel's broadcasting feature to broadcast the event to the app
channel.
- Listen for the event in Vue.js
Finally, you need to listen for the event in your Vue.js component and update the progress bar. Modify the
UploadComponent.vue
file as follows:
import Echo from 'laravel-echo';
// ...
export default {
// ...
mounted() {
Echo.channel('app')
.listen('FileUploaded', (e) => {
const file = this.files.find(f => f.name === e.path.split('/').pop());
if (file) {
this.$set(file, 'progress', 100);
}
});
}
}
This code listens for the FileUploaded
event on the app
channel and updates the progress bar for the corresponding file.
That's it! You now have an asynchronous multiple file upload component with a progress bar in Laravel using jQuery, AJAX, Laravel Echo, and Vue.js.