...

Implementing Dropzone.js for Chunked File Uploads in Laravel

Uploading large files efficiently is a common challenge in web applications. Dropzone.js provides an easy-to-use drag-and-drop file upload interface, and when combined with Laravel, it enables chunked file uploads to handle large files without hitting server limits. In this post, we will walk through setting up Dropzone.js with Laravel for chunked file uploads.

Prerequisites

Before you begin, ensure you have the following:

A Laravel project set up

jQuery and Dropzone.js installed

A configured Laravel route and controller for handling file uploads

Setting Up Dropzone.js

First, add the Dropzone.js script in your Blade template:

@push('dropzonejs')
<script src="https://cdnjs.cloudflare.com/ajax/libs/dropzone/5.9.2/min/dropzone.min.js"></script>
<script>
    Dropzone.autoDiscover = false;

    $(document).ready(function() {
        var myDropzone = new Dropzone("#my-awesome-dropzone-anyfile", {
            url: "{{ route('dropzone.uploader') }}",
            acceptedFiles: "image/*",
            method: "POST",
            paramName: 'file',
            maxFilesize: 2024,
            addRemoveLinks: true,
            autoProcessQueue: false,
            parallelUploads: 100,
            chunking: true,
            chunkSize: 2 * 1024 * 1024,
            forceChunking: true,
            retryChunks: true,
            retryChunksLimit: 3,
            timeout: 0,
            capture: 'camera',

            init: function() {
                console.log("Dropzone initialized");
                this.on("success", function(file, response) {
                    console.log("Upload successful", response);
                });
                this.on("error", function(file, errorMessage, xhr) {
                    console.error("Upload Error:", errorMessage);
                });
                document.querySelector("#submit-all").addEventListener("click", () => {
                    console.log("Submitting all files...");
                    this.processQueue();
                });
            }
        });
    });
</script>
@endpush

Creating Laravel File Upload Controller

Next, create a DropZoneController to handle the chunked file uploads.

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Log;
use Pion\Laravel\ChunkUpload\Handler\HandlerFactory;
use Pion\Laravel\ChunkUpload\Receiver\FileReceiver;

class DropZoneController extends Controller
{
    public function dropUploader(Request $request)
    {
        Log::info('Incoming Request for Large Uploader', [
            'ip' => $request->ip(),
        ]);
        if ($request->file('file')) {
            $fileReceiver = new FileReceiver("file", $request, HandlerFactory::classFromRequest($request));
            if (!$fileReceiver->isUploaded()) {
                return response()->json(['error' => 'No file uploaded!'], 400);
            }

            $save = $fileReceiver->receive();
            if ($save->isFinished()) {
                return $this->saveFile($save->getFile());
            }

            return response()->json(["done" => $save->handler()->getPercentageDone(), 'status' => true]);
        }

        return response()->json(['error' => 'No file uploaded!'], 400);
    }

    protected function saveFile(UploadedFile $file)
    {
        $fileName = $this->createFilename($file);
        $filePath = $file->storeAs('dropzone/uploads', $fileName, 'public');
        Log::info("File saved at: " . $filePath);

        return response()->json([
            'path' => $filePath,
            'name' => $fileName,
            'mime_type' => $file->getMimeType()
        ]);
    }

    protected function createFilename(UploadedFile $file)
    {
        $extension = $file->getClientOriginalExtension();
        $filename = str_replace("." . $extension, "", $file->getClientOriginalName());
        return $filename . "_" . strtoupper(md5(time())) . "." . $extension;
    }
}

Configuring Routes

Define a route for handling the file upload request.

use App\Http\Controllers\DropZoneController;

Route::post('/dropzone/uploader', [DropZoneController::class, 'dropUploader'])->name('dropzone.uploader');

By integrating Dropzone.js with Laravel, you can efficiently upload large files using chunked uploads. This approach prevents server overload and allows users to upload multiple files seamlessly. Happy coding!

William Anderson

I am a versatile Full-Stack Web Developer with a strong focus on Laravel, Livewire, Vue.js, and Tailwind CSS. With extensive experience in backend development, I specialize in building scalable, efficient, and high-performance web applications.