ankitpokhrel/tus-php
PHP server/client implementation of the tus resumable upload protocol. Supports large, chunked uploads with pause/resume, retries, and offsets; integrates with popular PHP frameworks and storage backends, offering configurable middleware, events, and validation.
composer require ankitpokhrel/tus-php
php artisan vendor:publish --provider="AnkitPokhrel\Tus\TusServiceProvider" --tag="tus-config"
filesystem or s3):
// config/tus.php
'storage' => [
'driver' => 'local',
'path' => storage_path('app/tus-uploads'),
],
routes/web.php:
use AnkitPokhrel\Tus\TusRoute;
TusRoute::upload('upload', [
'store' => 'AnkitPokhrel\Tus\Storage\FileSystem',
'path' => storage_path('app/tus-uploads'),
]);
const upload = new tus.Upload(file, {
endpoint: '/upload',
metadata: { filename: 'test.pdf' },
retryDelays: [0, 1000, 3000, 5000]
});
upload.start();
max_size in tus.php (e.g., max_size => 5 * 1024 * 1024 * 1024 for 5GB).OPTIONS to /upload → Server responds with Upload-Offset: 0.Upload-Length header.Upload-Offset at current position.onComplete hook (e.g., move file to final location).// app/Http/Kernel.php
'tus' => [
\AnkitPokhrel\Tus\Middleware\CheckUploadSize::class,
\AnkitPokhrel\Tus\Middleware\CheckUploadMethod::class,
],
tus.upload.complete to process files post-upload:// app/Listeners/HandleUploadComplete.php
public function handle(UploadComplete $event) {
$file = $event->getFile();
// Move to S3, generate thumbnails, etc.
}
AnkitPokhrel\Tus\Storage\StorageInterface for S3, database, etc.:class S3Storage implements StorageInterface {
public function storeChunk($uploadId, $chunk) { ... }
public function finalize($uploadId, $metadata) { ... }
}
TusRoute::progress('progress/{uploadId}', [
'store' => 'AnkitPokhrel\Tus\Storage\FileSystem',
]);
upload.setHeader('Upload-Metadata', JSON.stringify({
user_id: 123,
file_type: 'video'
}));
Access-Control-Allow-Origin headers. Use middleware:Header::set('Access-Control-Allow-Origin', '*');
Header::set('Access-Control-Allow-Methods', 'OPTIONS, POST, PATCH, DELETE');
upload_id to isolate files.memory_limit. Adjust or stream chunks directly to storage.// config/tus.php
'debug' => env('APP_DEBUG', false),
curl -X OPTIONS http://your-app/upload -H "Upload-Offset: 0"
400 Bad Request: Invalid headers (e.g., missing Upload-Length).403 Forbidden: Missing Upload-Metadata or size limits exceeded.onCreate, onUpload, onComplete in your storage backend:class CustomStorage extends FileSystem {
public function onComplete($uploadId, $metadata) {
// Add post-processing logic
parent::onComplete($uploadId, $metadata);
}
}
onCreate:public function onCreate($uploadId, $metadata) {
if (!in_array($metadata['file_type'], ['video', 'image'])) {
throw new \RuntimeException('Invalid file type');
}
}
onTerminate to delete partial uploads:public function onTerminate($uploadId) {
$this->delete($uploadId);
}
AWSS3 adapter with stream_wrappers for direct uploads.event(new UploadComplete($uploadId, $metadata));
// Dispatch to queue in onComplete
How can I help you explore Laravel packages today?