PHP code example of netipar / laravel-chunky

1. Go to this page and download the library: Download netipar/laravel-chunky library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

netipar / laravel-chunky example snippets


// Backend: Listen for completed uploads
// EventServiceProvider
protected $listen = [
    \NETipar\Chunky\Events\UploadCompleted::class => [
        \App\Listeners\ProcessUploadedFile::class,
    ],
];

#[On('chunky-upload-completed')]
public function handleUpload(array $data): void
{
    // Default payload: $data['uploadId'], $data['fileName'], $data['fileSize']
    //
    // Set `chunky.broadcasting.expose_internal_paths = true` in
    // config/chunky.php to additionally receive $data['finalPath'] and
    // $data['disk']. By default they're stripped to avoid leaking
    // server-internal paths to the browser.
}

'routes' => [
    'prefix' => 'api/chunky',
    'middleware' => ['api', 'auth:sanctum'],
],

namespace NETipar\Chunky\Authorization;

interface Authorizer
{
    public function canAccessUpload(?Authenticatable $user, UploadMetadata $upload): bool;
    public function canAccessBatch(?Authenticatable $user, BatchMetadata $batch): bool;
}

use NETipar\Chunky\Authorization\Authorizer;
use NETipar\Chunky\Authorization\DefaultAuthorizer;

$this->app->singleton(Authorizer::class, function ($app) {
    return new class extends DefaultAuthorizer
    {
        public function canAccessUpload(?Authenticatable $user, UploadMetadata $upload): bool
        {
            // Admins access everything
            if ($user?->is_admin) {
                return true;
            }

            // Teammates share access
            if ($upload->userId !== null) {
                $owner = User::find($upload->userId);
                if ($owner && $user?->team_id === $owner->team_id) {
                    return true;
                }
            }

            return parent::canAccessUpload($user, $upload);
        }
    };
});

use NETipar\Chunky\Facades\Chunky;

Chunky::simple('documents', 'uploads/documents', [
    'max_size' => 50 * 1024 * 1024, // 50MB
    'mimes' => ['application/pdf', 'image/jpeg', 'image/png'],
]);

namespace App\Chunky;

use NETipar\Chunky\ChunkyContext;
use NETipar\Chunky\Data\UploadMetadata;

class ProfileAvatarContext extends ChunkyContext
{
    public function name(): string
    {
        return 'profile_avatar';
    }

    public function rules(): array
    {
        return [
            'file_size' => ['max:5242880'], // 5MB
            'mime_type' => ['in:image/jpeg,image/png,image/webp'],
        ];
    }

    public function save(UploadMetadata $metadata): void
    {
        auth()->user()
            ->addMediaFromDisk($metadata->finalPath, $metadata->disk)
            ->toMediaCollection('avatar');
    }
}

'contexts' => [
    App\Chunky\ProfileAvatarContext::class,
    App\Chunky\DocumentContext::class,
],

use NETipar\Chunky\Facades\Chunky;

public function boot(): void
{
    Chunky::register(ProfileAvatarContext::class);
}

use NETipar\Chunky\Facades\Chunky;

public function boot(): void
{
    Chunky::context(
        'documents',
        rules: fn () => [
            'file_size' => ['max:104857600'], // 100MB
            'mime_type' => ['in:application/pdf,application/zip'],
        ],
    );
}

use NETipar\Chunky\Events\UploadCompleted;
use NETipar\Chunky\Events\ChunkUploaded;
use NETipar\Chunky\Events\FileAssembled;

protected $listen = [
    UploadCompleted::class => [
        \App\Listeners\ProcessUploadedFile::class,
        \App\Listeners\NotifyUserAboutUpload::class,
    ],
    ChunkUploaded::class => [
        \App\Listeners\TrackUploadProgress::class,
    ],
];

namespace App\Listeners;

use NETipar\Chunky\Events\UploadCompleted;
use Illuminate\Support\Facades\Storage;

class ProcessUploadedFile
{
    public function handle(UploadCompleted $event): void
    {
        // Full UploadMetadata DTO available via $event->upload
        $upload = $event->upload;

        Storage::disk($upload->disk)->move(
            $upload->finalPath,
            "documents/{$upload->uploadId}.zip",
        );

        // Shorthand properties also available for convenience:
        // $event->uploadId, $event->finalPath, $event->disk, $event->metadata
    }
}

use Illuminate\Support\Facades\Broadcast;

Broadcast::channel('chunky.uploads.{uploadId}', function ($user, $uploadId) {
    // Verify the user owns this upload
    return true;
});

Broadcast::channel('chunky.batches.{batchId}', function ($user, $batchId) {
    return true;
});

// routes/channels.php
Broadcast::channel('chunky.user.{userId}', function ($user, $userId) {
    return (int) $user->id === (int) $userId;
});

use NETipar\Chunky\Facades\Chunky;

// Register contexts
Chunky::register(ProfileAvatarContext::class);
Chunky::context('documents', rules: fn () => [...], save: fn ($metadata) => ...);

// Programmatic initiation (returns InitiateResult DTO)
$result = Chunky::initiate('large-file.zip', 524288000, 'application/zip');
// $result->uploadId, $result->chunkSize, $result->totalChunks

// Query upload status (returns UploadMetadata DTO)
$status = Chunky::status($uploadId);
// $status->progress(), $status->fileName, $status->status, etc.

// Batch upload (returns BatchMetadata DTO)
$batch = Chunky::initiateBatch(totalFiles: 5, context: 'documents');
// $batch->batchId, $batch->totalFiles, $batch->status

// Add file to batch (returns InitiateResult DTO with batchId)
$file = Chunky::initiateInBatch($batch->batchId, 'photo.jpg', 5242880);
// $file->uploadId, $file->batchId

// Query batch status (returns BatchMetadata DTO)
$batch = Chunky::getBatchStatus($batchId);
// $batch->completedFiles, $batch->failedFiles, $batch->isFinished()

use NETipar\Chunky\Exceptions\ChunkyException;
use NETipar\Chunky\Exceptions\ChunkIntegrityException;
use NETipar\Chunky\Exceptions\UploadExpiredException;

try {
    $manager->uploadChunk($uploadId, $chunkIndex, $file);
} catch (ChunkIntegrityException $e) {
    // SHA-256 checksum mismatch
} catch (UploadExpiredException $e) {
    // Upload has expired (past 24h default)
} catch (ChunkyException $e) {
    // Base exception (catches all above)
}
bash
php artisan vendor:publish --tag=chunky-config
bash
php artisan migrate
vue
<script setup>
import { useChunkUpload, useUploadEcho } from '@netipar/chunky-vue3';

const echo = inject('echo');
const { upload, uploadId } = useChunkUpload();

useUploadEcho(echo, uploadId, (data) => {
    console.log('Upload ready:', data.fileName);
});
</script>
tsx
import { useChunkUpload, useUploadEcho } from '@netipar/chunky-react';

function FileUpload({ echo }) {
    const { upload, uploadId } = useChunkUpload();

    useUploadEcho(echo, uploadId, (data) => {
        console.log('Upload ready:', data.fileName);
    });

    // ...
}
bash
php artisan vendor:publish --tag=chunky-config