Download the PHP package hanfy/batch-zip-stream without Composer
On this page you can find all versions of the php package hanfy/batch-zip-stream. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download hanfy/batch-zip-stream
More information about hanfy/batch-zip-stream
Files in hanfy/batch-zip-stream
Package batch-zip-stream
Short Description A memory-efficient, batchable PHP library to stream ZIP archive creation incrementally.
License MIT
Informations about the package batch-zip-stream
Batch ZIP Stream Engine
A production-grade batch ZIP streaming implementation in PHP that creates ZIP archives incrementally across multiple executions while streaming output to abstract writable streams.
Table of Contents
- Overview
- Architecture
- Installation
- Quick Start
- Stream-Agnostic API
- Core Concepts
- API Reference
- State Persistence
- Error Handling
- ZIP64 Support
- Encryption Support
- Extensibility
- Security Considerations
- Performance
- File Structure
Overview
Problem Statement
Creating large ZIP archives in web environments presents several challenges:
- Execution time limits: PHP scripts have maximum execution times
- Memory limits: Large files cannot be loaded entirely into memory
- Resumability: Interrupted operations should be resumable
- Cloud storage: Output may go to cloud storage, not local disk
- Scale: Archives may contain millions of files
Solution
This library provides a batch-based ZIP creation engine that:
- ✅ Splits ZIP creation across multiple independent executions
- ✅ Streams files incrementally (no memory exhaustion)
- ✅ Persists state externally (fully resumable)
- ✅ Writes to abstract streams (cloud-compatible)
- ✅ Full ZIP64 support (>4GB archives, >65535 files)
- ✅ Explicit failure handling (no silent corruption)
- ✅ Memory-efficient architecture for 1M+ files without memory issues
- ✅ Stream-agnostic API for cloud storage, HTTP uploads, and more
Memory Characteristics
| File Count | State File Size | Memory Usage |
|---|---|---|
| 1,000 | ~500 bytes | ~1 MB |
| 10,000 | ~500 bytes | ~1 MB |
| 100,000 | ~500 bytes | ~1 MB |
| 1,000,000 | ~500 bytes | ~1 MB |
State file size remains constant regardless of archive size because file entries are stored in a separate append-only file that is streamed, never fully loaded into memory.
Architecture
Class Responsibilities
Data Flow
Installation
Requirements
- PHP 7.4+
zlibextension (for deflate compression)hashextension (for CRC32 calculation)opensslextension (required for WinZip AES-256 encryption)
Via Composer (Recommended)
You can install the library via Composer:
Then include the Composer autoloader in your script:
Manual Installation (No Composer)
If you are not using Composer, download/clone this repository and include the built-in autoloader:
Quick Start
Simple Single-Batch Usage
Multi-Batch Usage with Persistence
Streaming Large Files
Large Archive (1M+ Files)
Stream-Agnostic API
The architecture supports any output stream, not just files. This enables:
- Cloud storage (S3, GCS, Azure Blob)
- HTTP chunked uploads
- In-memory buffers (for testing)
- Custom stream implementations
Creating Sessions with Custom Streams
Using a Stream Factory
Using a Pre-Created Stream
In-Memory ZIP Creation
Adding Files from Streams
The addFileFromStream() method accepts any ReadableStreamInterface:
Available Session Methods
| Method | Description |
|---|---|
startSession($sessionId) |
Start or resume a session, returns session ID |
getWriter() |
Get the BatchZipWriter instance |
addFile($path, $sourcePath, $compressionMethod, $encryptionMethod, $password) |
Add file from local filesystem with optional compression, encryption, and custom password |
addFileFromString($path, $content, $compressionMethod, $encryptionMethod, $password) |
Add file from string content with optional compression, encryption, and custom password |
addFileFromStream($path, $stream, $compressionMethod, $modificationTime) |
Add file from any ReadableStreamInterface with optional compression and modification time |
addEmptyDirectory($path, $modificationTime) |
Add an empty directory with optional modification time |
saveProgress() |
Persist current session progress and state |
finalize($comment) |
Write CDR, EOCD, and complete the archive |
cleanup() |
Remove state files and close resources for the current session |
abort($reason, $deleteArchive) |
Mark session as failed, close resources, and optionally delete the partial archive |
close() |
Close session streams and locks without deleting state (useful to pause a batch) |
getStream() |
Get the current output stream |
getState() |
Get the ArchiveState instance |
getStats() |
Get session statistics (count, sizes, path, etc.) |
exists($sessionId) |
Check if a session's state files exist |
cleanupOldSessions($maxAgeSeconds) |
Clean up stale or orphaned sessions older than the specified seconds |
listSessions() |
List all active session IDs |
Core Concepts
State Management
The library uses a split-state architecture for memory efficiency:
ArchiveState(~500 bytes): Session ID, phase, offsets, countersFileEntryStore(streamed): Line-delimited JSON, append-only
Critical Rule: Only ArchiveState is persisted between batches. ZIP writers, streams, and compression contexts are NEVER serialized.
File Entries
Each file in the archive is represented by a FileEntry:
Phases
Archives progress through phases:
- INITIALIZING: Fresh archive, no files added
- ADDING_FILES: Files being added
- FINALIZING: Writing Central Directory
- COMPLETED: Successfully finished
- FAILED: Error occurred
API Reference
BatchZipSession
High-level session manager.
Constructors
Methods
BatchZipWriter
Low-level memory-efficient writer.
Constructor
Methods
| Method | Description |
|---|---|
addFile(string $filename, ReadableStreamInterface $source, int $method = DEFLATE, ?int $mtime = null, int $enc = ENC_NONE, ?string $password = null) |
Add a file from a stream |
addFileFromString(string $filename, string $data, int $method = DEFLATE, ?int $mtime = null, int $enc = ENC_NONE, ?string $password = null) |
Add a file from string data |
finalize(string $comment = '') |
Write Central Directory and EOCD |
close() |
Close the output stream |
getState() |
Get the current archive state |
getEntryStore() |
Get the entry store |
canAddFiles() |
Check if files can be added |
canFinalize() |
Check if archive can be finalized |
State Persistence
File-Based Persistence
Files per Session
Each session creates:
{sessionId}.json- State (~500 bytes){sessionId}.entries- Entry store (append-only){sessionId}.lock- Lock file
Custom Persistence
Implement StatePersistenceInterface for custom backends (Redis, database, etc.):
Error Handling
Exception Hierarchy
Error Handling Strategy
- Any write failure invalidates the entire archive
- State is marked as FAILED on any exception
- No silent fallbacks - all errors throw exceptions
- Central Directory is NEVER written if any file failed
ZIP64 Support
Full ZIP64 support for:
- Archives larger than 4GB
- Individual files larger than 4GB
- More than 65,535 files
ZIP64 is automatically enabled when needed:
ZIP64 Structures
When ZIP64 is required, the following structures are added:
- ZIP64 Extra Field in Central Directory entries
- ZIP64 End of Central Directory Record
- ZIP64 End of Central Directory Locator
Encryption Support
The library supports securing ZIP archives using standard zip encryption methods:
- Traditional PKWARE Encryption (
ZipFormat::ENC_TRADITIONAL): Highly compatible across older extraction tools but cryptographically weak. - WinZip AES-256 Strong Encryption (
ZipFormat::ENC_AES_256): Industry-standard strong encryption. Requires theopensslPHP extension enabled in PHP.
Setting a Global Password
You can configure a global password during BatchZipSession construction:
Encrypting Files
To encrypt files, pass the encryption method to the addFile or addFileFromString methods.
Overriding Passwords per File
You can override the global password for specific files by passing a custom password as the final parameter.
Extensibility
Custom Output Streams
Implement WritableStreamInterface for cloud storage:
Built-in Streams
The library provides several built-in stream implementations:
MemoryWritableStream
An in-memory buffer for testing or small archives:
FileWritableStream
Standard file output stream:
BufferedWritableStream
Wraps another stream with buffering:
CallbackWritableStream
Invokes a callback on each write:
Custom Input Streams
Implement ReadableStreamInterface for custom sources:
Security Considerations
Path Traversal
Filenames are automatically sanitized:
- Leading slashes removed
- Backslashes converted to forward slashes
- Invalid characters replaced
../sequences are preserved but validated
Validation
The FileEntryStore provides entry-level validation:
- JSON integrity per entry
- Duplicate filename detection
- Entry metadata validation via
FileEntry.validate()
Performance
Memory Usage
- Files are read in configurable chunks (default 64KB)
- Compression uses streaming deflate context
- CRC32 is calculated incrementally
- No file is ever fully loaded into memory
- State stays ~500 bytes regardless of file count
- Entry store is streamed via generator during finalization
Tuning Options
Buffered Output
For better I/O performance with small writes:
File Structure
All versions of batch-zip-stream with dependencies
ext-zlib Version *
ext-hash Version *
ext-openssl Version *