Creating a Laravel package for chunked video upload involves several steps. The package will include the necessary backend logic for handling chunked uploads and provide an easy way to integrate the functionality into any Laravel application.

Step 1: Create the Package Structure

  1. Create the Package Directory:

    mkdir -p packages/YourVendor/ChunkedVideoUpload
    cd packages/YourVendor/ChunkedVideoUpload
    
  2. Initialize Composer:

    composer init
    
  3. Setup the Directory Structure:

    packages/YourVendor/ChunkedVideoUpload
    ├── src
    │   ├── ChunkedVideoUploadServiceProvider.php
    │   ├── Controllers
    │   │   └── VideoUploadController.php
    │   ├── routes
    │   │   └── web.php
    ├── composer.json
    └── README.md
    

Step 2: Setup Composer

Edit the composer.json file to include the necessary information and autoloading:

{
    "name": "your-vendor/chunked-video-upload",
    "description": "A Laravel package for chunked video uploads",
    "type": "library",
    "autoload": {
        "psr-4": {
            "YourVendor\\ChunkedVideoUpload\\": "src/"
        }
    },
    "require": {
        "php": ">=7.4",
        "illuminate/support": ">=8.0"
    },
    "extra": {
        "laravel": {
            "providers": [
                "YourVendor\\ChunkedVideoUpload\\ChunkedVideoUploadServiceProvider"
            ]
        }
    },
    "minimum-stability": "dev",
    "prefer-stable": true
}

Step 3: Create the Service Provider

In src/ChunkedVideoUploadServiceProvider.php:

<?php

namespace YourVendor\ChunkedVideoUpload;

use Illuminate\Support\ServiceProvider;

class ChunkedVideoUploadServiceProvider extends ServiceProvider
{
    public function boot()
    {
        // Load routes
        $this->loadRoutesFrom(__DIR__ . '/routes/web.php');

        // Publish configuration
        $this->publishes([
            __DIR__ . '/config/chunkedvideoupload.php' => config_path('chunkedvideoupload.php'),
        ]);
    }

    public function register()
    {
        // Merge configuration
        $this->mergeConfigFrom(
            __DIR__ . '/config/chunkedvideoupload.php', 'chunkedvideoupload'
        );
    }
}

Step 4: Create the Controller

In src/Controllers/VideoUploadController.php:

<?php

namespace YourVendor\ChunkedVideoUpload\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use App\Http\Controllers\Controller;

class VideoUploadController extends Controller
{
    public function uploadChunk(Request $request)
    {
        $chunk = $request->file('file');
        $chunkIndex = $request->input('chunk');
        $totalChunks = $request->input('totalChunks');
        $fileId = $request->input('fileId', uniqid()); // Generate a unique identifier for the file

        // Temporary storage for chunks
        $tempDir = storage_path('app/temp_uploads');
        if (!file_exists($tempDir)) {
            mkdir($tempDir, 0777, true);
        }

        // Save the chunk
        $chunk->move($tempDir, $fileId . '-' . $chunkIndex);

        // If this is the last chunk, combine all chunks
        if ($chunkIndex == $totalChunks - 1) {
            $finalPath = storage_path('app/videos/' . $fileId . '.mp4');
            $outputFile = fopen($finalPath, 'ab');

            for ($i = 0; $i < $totalChunks; $i++) {
                $chunkPath = $tempDir . '/' . $fileId . '-' . $i;
                $chunkData = file_get_contents($chunkPath);
                fwrite($outputFile, $chunkData);
                unlink($chunkPath); // Remove chunk after merging
            }

            fclose($outputFile);

            return response()->json(['message' => 'File upload complete'], 200);
        }

        return response()->json(['message' => 'Chunk uploaded'], 200);
    }
}

Step 5: Define Routes

In src/routes/web.php:

<?php

use Illuminate\Support\Facades\Route;
use YourVendor\ChunkedVideoUpload\Controllers\VideoUploadController;

Route::post('/upload-chunk', [VideoUploadController::class, 'uploadChunk']);

Step 6: Configuration File

In src/config/chunkedvideoupload.php:

<?php

return [
    'chunk_size' => 1 * 1024 * 1024, // 1MB
];

Step 7: Register the Package

In your Laravel project’s composer.json, add the repository and require the package:

"repositories": [
    {
        "type": "path",
        "url": "packages/YourVendor/ChunkedVideoUpload"
    }
],
"require": {
    "your-vendor/chunked-video-upload": "*"
}

Run composer update to install the package.

Step 8: Publish the Configuration

Run the following command to publish the configuration file:

php artisan vendor:publish --provider="YourVendor\ChunkedVideoUpload\ChunkedVideoUploadServiceProvider"

Step 9: Use the Package

In your Laravel application, you can now use the chunked upload functionality by sending POST requests to /upload-chunk.

Step 10: Frontend Integration

For the frontend, you can use the React component provided earlier to handle chunked uploads:

import React, { useState } from 'react';

const ChunkedVideoUpload = () => {
    const [file, setFile] = useState(null);

    const handleFileChange = (event) => {
        setFile(event.target.files[0]);
    };

    const uploadFile = async () => {
        if (!file) {
            alert('Please select a file first');
            return;
        }

        const chunkSize = 1 * 1024 * 1024; // 1MB chunks
        const totalChunks = Math.ceil(file.size / chunkSize);

        for (let i = 0; i < totalChunks; i++) {
            const start = i * chunkSize;
            const end = Math.min(start + chunkSize, file.size);
            const chunk = file.slice(start, end);

            const formData = new FormData();
            formData.append('file', chunk);
            formData.append('chunk', i);
            formData.append('totalChunks', totalChunks);

            await fetch('/upload-chunk', {
                method: 'POST',
                body: formData,
            });
        }

        alert('Upload complete!');
    };

    return (
        <div>
            <input type="file" onChange={handleFileChange} />
            <button onClick={uploadFile}>Upload</button>
        </div>
    );
};

export default ChunkedVideoUpload;

Step 11: Testing

Ensure that your /upload-chunk endpoint is reachable and working correctly by uploading a large video file using the React component.

This setup provides a modular and reusable package for handling chunked video uploads in Laravel, along with a React component for the frontend.