Download the PHP package resumable/chunked-uploader without Composer
On this page you can find all versions of the php package resumable/chunked-uploader. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download resumable/chunked-uploader
More information about resumable/chunked-uploader
Files in resumable/chunked-uploader
Package chunked-uploader
Short Description Enterprise-grade, framework-agnostic PHP library for handling large file uploads via chunking with stream-based assembly, resume capability, and cryptographic integrity checks.
License MIT
Homepage https://github.com/resumable/chunked-uploader
Informations about the package chunked-uploader
Resumable Chunked Uploader
Enterprise-grade, framework-agnostic PHP 8.2 library for handling large file uploads via chunking with constant-memory stream assembly, resume capability, and cryptographic integrity checks.
Chunks are persisted independently, progress is kept in a durable store (Redis or a relational database), and the final file is assembled using native PHP streams — never buffering the whole file into memory, regardless of how large it is.
Table of contents
- Highlights
- Architecture
- Core benefits
- Installation
- Standalone PHP quickstart
- Framework integration
- Laravel 10 / 11
- Symfony 6 / 7
- Vanilla JavaScript client
- Security model
- API reference
- Configuration options
- Testing
- License
Highlights
- O(1) memory chunk assembly via
fopen()+stream_copy_to_stream(). - Resume support for out-of-order chunks and interrupted requests.
- Atomic progress updates in Redis (optimistic locking).
- HMAC tokens bound to upload metadata and client context.
- Magic-byte MIME validation (only reads the first 4096 bytes).
- Strict path sanitization against directory traversal.
- Optional ClamAV scanning and Redis rate limiting.
- Atomic failure cleanup removes a stored chunk when its metadata update fails, so transient database errors do not create permanent orphan bytes.
- Bounded cleanup scans local directories, S3 pages, Redis cursors, and PDO rows incrementally, including S3 deletion batches larger than 1,000 objects.
ChunkUploaderis the single canonical coordinator.- Optional PHP 8 attributes provide endpoint-specific immutable config overrides without changing global defaults.
- Flysystem v3 storage is available as an optional driver.
- Zero framework dependency in the core package.
- Laravel and Symfony bridges + a dependency-free vanilla JS client.
Architecture
Data flow for a single chunk:
Core benefits
| Benefit | How it works |
|---|---|
| Low memory | Assembly streams chunk-by-chunk through a fixed 4 MiB buffer. A 10 GB file needs under 10 MiB of PHP memory. |
| Resumable | Progress persists per-chunk. Any client can query missing indices and resume exactly where it stopped. |
| Idempotent | Re-sending an already-accepted chunk is a no-op — no duplicated bytes, no corruption. |
| Secure | Magic-byte MIME checks, HMAC token verification, traversal-safe paths, and optional ClamAV scanning. |
| Out-of-order safe | Chunks may arrive in any order; assembly only runs when every index is present. |
Installation
Requirements:
- PHP ^8.2
ext-json- One of
ext-redisorpredis/predis(for the Redis metadata driver) ext-pdo(for the PDO metadata driver)aws/aws-sdk-php(for the S3 storage driver)
Standalone PHP quickstart
Create one Chunk per HTTP request. index is zero-based. Retrying an
already-accepted index is safe and idempotent.
Framework integration
Laravel 10 / 11
1. Register the service provider
In bootstrap/providers.php (Laravel 11) or config/app.php (Laravel 10):
2. Publish configuration (optional)
Then adjust config/chunk-uploader.php (allowed MIME types, spool directory,
storage driver, etc.).
New in this version: token_salt (binds tokens to a client fingerprint),
virus_scanning (ClamAV host/port), and rate_limiting (Redis-backed chunk
flood protection) — all with matching .env variable names (see the config
file for the full list).
3. Use the Facade
4. Add routes (see the example controller)
A complete, copy-pasteable controller lives at
examples/laravel/ChunkUploadController.php.
Symfony 6 / 7
1. Enable the bundle
2. Configure the bundle
3. Add routes via attribute on the controller
The example at examples/symfony/ChunkUploadController.php
uses attribute routing and constructor injection, so no routing YAML is needed.
Vanilla JavaScript client
A 100% dependency-free ES6+ client, using Blob.prototype.slice(), the Fetch
API and FormData, is included in examples/vanilla-js/.
Features:
- Splits a
Fileinto binary chunks withfile.slice(start, end). - Sends each chunk as
multipart/form-dataviafetch(). - Automatic retry with exponential backoff on transient failures.
pause()/resume()for interactive control.missingChunks()queriesGET {endpoint}/status/{id}so a partially uploaded file resumes instead of restarting.- Works in any modern browser with native
fetch,FormData, andBlob.
Open examples/vanilla-js/index.html in a
browser for a ready-to-run drag-and-drop demo.
Security model
- Tokens —
UploadTokenServiceissues HMAC-SHA256 tokens bound to the upload identifier, chunk count, total size, and an optional client salt (IP / fingerprint). Verification useshash_equals()(constant-time). - Paths —
PathSanitizerrejects null bytes, directory separators, traversal markers (..,../), and unsafe identifiers. Never build a filesystem path from user input without running it through the sanitizer. - MIME —
MagicByteValidatorinspects only the first 4096 bytes viafinfoand compares against an allow-list. Client-supplied MIME headers are never trusted. - Extension matching —
ExtensionMimeMatchRulerejects files whose claimed extension disagrees with their detected MIME type. - Malware —
ClamAvScannerstreams data toclamdover the INSTREAM protocol in 1 MiB chunks. UseNullVirusScannerwhen scanning is handled elsewhere. - Abuse —
RedisRateLimitercan key limits per IP, user, or upload token and applies them before accepting chunk bodies. - Storage — Keep temporary and final directories outside the public document root, and configure permissions and retention deliberately.
API reference
ChunkUploaderInterface
| Method | Description |
|---|---|
processChunk(Chunk $chunk): UploadState |
Validates the token, persists the chunk, advances progress, and assembles when complete. Idempotent and concurrent-safe. |
cancelUpload(string $identifier): void |
Removes chunks and metadata. Idempotent for unknown identifiers. |
getStatus(string $identifier): ?UploadState |
Reads the current state of an upload, or null if unknown. |
Chunk (readonly DTO)
identifier, token, index, totalChunks, chunkSize, totalSize,
tmpFilePath, originalFilename, and optional checksum.
UploadState (readonly DTO)
identifier, totalChunks, totalSize, originalFilename, uploadedChunks,
isCompleted, finalPath; plus hasChunk(), isComplete(),
withUploadedChunk(), and withFinalPath().
Contracts
| Contract | Methods |
|---|---|
ChunkStorageInterface |
store, getChunkStream, deleteChunks, cleanOrphanedChunks |
MetadataRepositoryInterface |
save, get, delete, markChunkAsUploaded, cleanExpired |
ProgressTrackerInterface |
getPercentage, isComplete, getMissingChunkIndices |
FileAssemblerInterface |
assemble(UploadState, ChunkStorageInterface): string |
ValidationRuleInterface |
validate(Chunk): void |
ChunkValidatorInterface |
validate(Chunk): bool |
VirusScannerInterface |
scan(string): void |
EventDispatcherInterface |
dispatch(object): object |
Endpoint-specific attributes
Global Laravel or Symfony configuration remains the default. A controller method can opt into a narrower immutable configuration for its own uploads:
The core resolver accepts either a ReflectionMethod or ReflectionClass and
returns the unchanged global instance when no attribute is present.
Configuration options
| Setting | Default | Description |
|---|---|---|
maxChunkSize |
5 MiB | Hard limit of a single chunk. |
maxFileSize |
100 MiB | Hard limit of the assembled file. |
maxChunks |
1000 | Max chunks per upload (DoS guard). |
allowedMimeTypes |
[] |
Whitelist; empty = any verified type. |
spoolDirectory |
/tmp/chunked-uploader |
Chunk + final assembly dir. |
garbageCollectionTtl |
3600 s | Incomplete-upload window before GC. |
identifierPattern |
^[a-zA-Z0-9_-]{1,128}$ |
Legal identifier pattern. |
tokenSalt |
'' |
Optional HMAC salt bound to client context. |
virusScanning |
disabled | ClamAV host/port (requires virus_scanning.enabled: true). |
rateLimiting |
disabled | Redis-backed chunk-flood guard (max_attempts, decay_seconds, key). |
Testing
The full suite runs completely offline: all disk I/O uses ephemeral temporary files that are cleaned up automatically; storage and metadata are in-memory doubles (FakeRedis, FakePdo); and Redis, S3, and ClamAV are never contacted. The suite covers:
- Unit tests against
PathSanitizer,MagicByteValidator,UploadTokenService,StreamAssembler(memory ceiling),ClamAvScanner(stream-pair seam),RedisRateLimiter,S3ChunkStorage, andPdoMetadataRepository(with Postgres/MySQL dialect assertions). - Feature tests for the full sequential upload flow, out-of-order resumable uploads, interrupted-upload recovery (idempotent retries, resume-from-missing-index, service-restart continuity), and both the Laravel and Symfony framework bridges.
License
MIT. See LICENSE.