Efficient file uploads are essential for modern web applications, enhancing user experience and functionality. In this tutorial, we'll build a robust Laravel file upload API with Vue.js integration using QuickAdminPanel, focusing on progress tracking and efficient handling.

By leveraging Vue.js for the front end and Laravel's powerful back end, we'll create a seamless file upload system complete with a progress bar and validation. QuickAdminPanel will streamline our development process, allowing us to focus on core features.

Prerequisites

To follow along with this tutorial, you should have:

  • Basic knowledge of Laravel, PHP, and Vue.js
  • Composer installed on your machine
  • Node.js and npm installed
  • An account with QuickAdminPanel

Setting up a new laravel project with quickadminpanel

First, we'll use QuickAdminPanel to generate a Laravel project with a built-in admin panel.

  1. Sign in to your QuickAdminPanel account.
  2. Create a new project and select "Standard Laravel" as the project type.
  3. Add necessary modules like Users management if needed.
  4. Download the generated Laravel project.

Unzip the project and navigate to the project directory:

cd your-project-directory

Install the dependencies:

composer install
npm install

Set up your .env file by copying the .env.example:

cp .env.example .env

Generate an application key:

php artisan key:generate

Run migrations:

php artisan migrate

Start the development server:

php artisan serve

Implementing a file upload API in laravel

We'll create an API endpoint to handle file uploads.

First, create a new controller:

php artisan make:controller API/FileUploadController

In app/Http/Controllers/API/FileUploadController.php, update the controller:

<?php

namespace App\Http\Controllers\API;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;

class FileUploadController extends Controller
{
    public function upload(Request $request)
    {
        $request->validate([
            'file' => 'required|file|max:10240', // Max 10MB
        ]);

        if ($request->file('file')->isValid()) {
            $path = $request->file('file')->store('uploads');

            return response()->json([
                'message' => 'File uploaded successfully.',
                'path' => $path,
            ], 200);
        }

        return response()->json([
            'message' => 'File upload failed.',
        ], 500);
    }
}

Next, add the route to routes/api.php:

Route::post('/upload', [App\Http\Controllers\API\FileUploadController::class, 'upload']);

Integrating vue.js for front-end file management

Our Laravel project already includes Vue.js, thanks to QuickAdminPanel. Let's create a Vue component for handling file uploads.

First, create a new Vue component:

Create a file resources/js/components/FileUpload.vue:

<template>
  <div>
    <input type="file" @change="selectFile" />
    <button @click="uploadFile" :disabled="!file">Upload</button>

    <div v-if="progress > 0">
      <progress :value="progress" max="100"></progress>
      <span>{{ progress }}%</span>
    </div>

    <div v-if="message">
      <p>{{ message }}</p>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      file: null,
      progress: 0,
      message: '',
    }
  },
  methods: {
    selectFile(event) {
      this.file = event.target.files[0]
    },
    uploadFile() {
      if (!this.file) return

      let formData = new FormData()
      formData.append('file', this.file)

      axios
        .post('/api/upload', formData, {
          headers: {
            'Content-Type': 'multipart/form-data',
          },
          onUploadProgress: (progressEvent) => {
            this.progress = Math.round((progressEvent.loaded * 100) / progressEvent.total)
          },
        })
        .then((response) => {
          this.message = response.data.message
          this.file = null
          this.progress = 0
        })
        .catch((error) => {
          console.error(error)
          this.message = 'File upload failed.'
          this.progress = 0
        })
    },
  },
}
</script>

Update your resources/js/app.js to register the component:

require('./bootstrap')

window.Vue = require('vue').default

Vue.component('file-upload', require('./components/FileUpload.vue').default)

const app = new Vue({
  el: '#app',
})

Compile your assets:

npm run dev

Displaying a progress bar for file uploads

The onUploadProgress event in axios allows us to track the upload progress, updating the progress bar accordingly.

In the Vue component, this code manages the progress:

onUploadProgress: (progressEvent) => {
  this.progress = Math.round(
    (progressEvent.loaded * 100) / progressEvent.total
  );
},

Adding the component to your view

Let's add the file-upload component to one of our views. For example, in resources/views/home.blade.php:

@extends('layouts.app')

@section('content')
<div class="container">
    <h1>File Upload</h1>
    <file-upload></file-upload>
</div>
@endsection

Best practices for handling large file uploads in laravel

When handling large file uploads, consider the following best practices:

  • Increase upload_max_filesize and post_max_size in your php.ini:
upload_max_filesize = 20M
post_max_size = 25M
  • Adjust the client_max_body_size if using Nginx:
client_max_body_size 25M;
  • Implement Chunked Uploads: For extremely large files, consider using chunked uploads to upload files in smaller pieces.

Troubleshooting common file upload issues

  • File Not Uploading: Ensure your API endpoint is correctly defined and that the route is accessible.
  • Progress Bar Not Updating: Check that the onUploadProgress function is correctly implemented in your axios request.
  • CORS Errors: If you're making API requests to a different domain, ensure that your server is configured to handle CORS.

Conclusion

By integrating Vue.js with Laravel using QuickAdminPanel, we've created a robust file upload system complete with progress tracking and validation. This setup enhances user experience and leverages the strengths of both the front-end and back-end frameworks.

For more advanced features like resumable uploads and cross-browser compatibility, consider integrating an open-source solution like Uppy, which offers a rich set of features and can be easily integrated with Laravel.