how to make asychronous multiple upload files with progress bar in laravel?

Updated: Jan 27, 2025

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:

  1. 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
  1. 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
});
  1. 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 the resources/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%.

  1. 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.

  1. 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.

  1. 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.