Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Zipstream Laravel Package

stechstudio/laravel-zipstream

Laravel ZipStream lets you create and stream ZIP archives on the fly without writing them to disk. Add files from strings or storage, then return a memory-efficient download response—ideal for large archives and dynamic exports.

Deep Wiki
Context7

Getting Started

Install & first look

composer require stechstudio/laravel-zipstream

The service provider and ZipStream facade are auto-discovered. Start with three files:

  1. README.md — the canonical API surface (create, add, addRaw, download, saveTo).
  2. src/ZipStream.php — public methods and their option arrays.
  3. vendor/maennchen/zipstream-php — the underlying streaming engine; compression, ZIP64, and header behavior all come from here.

First use case: a streamed export from a route/controller

use STS\ZipStream\Facades\ZipStream;

Route::get('/orders/{order}/download', function (Order $order) {
    return ZipStream::create("order-{$order->id}.zip")
        ->add(storage_path("app/invoices/{$order->id}.pdf"))
        ->addRaw($order->toJson(JSON_PRETTY_PRINT), 'order.json')
        ->download();
});

download() returns a Laravel/Symfony StreamedResponse, so you return it like any other response. No temp file is written — bytes go out as they are read.


Implementation Patterns

1. Chain calls in a controller, return the response Keep the route handler thin; download() sets Content-Type: application/zip and Content-Disposition: attachment. For inline previews use response() instead of download().

2. Mix sources in one archive Files on disk (add), arrays of paths (add([...])), and generated content (addRaw($string, $filename)) can be combined freely. This is the package's sweet spot: CSV/JSON manifests generated in memory next to existing PDFs/images.

3. Storage disks and remotes add() resolves local paths. For S3/HTTP sources, use the version's source/URL helpers (e.g. addUrl, source objects) if present; otherwise pull a stream from Storage::disk('s3')->readStream(...) and either wrap it in a source object or use addRaw for small payloads. Verify the exact signature against your installed version — this area changed between v2 and v3.

4. Reusable exporter service Wrap archive assembly in a small class returning a ZipStream instance:

class OrderZipExporter {
    public function build(Order $order): \STS\ZipStream\ZipStream { /* ... */ }
}

Then controllers call ->download() and queued jobs call ->saveTo(...). One builder, two delivery modes.

5. Auth via signed routes Since the download URL is the access point, protect the route with normal middleware, or generate a URL::temporarySignedRoute(...) and return the ZIP from that signed route. Don't try to authorize inside the ZIP builder.

6. Archive-then-link (queues) For large sets or slow remotes, build in a job and ->saveTo('exports/orders-2026.zip') on a disk, then email/notify a signed link. Streaming is great for interactive downloads; queued archiving is better for anything that risks hitting request timeouts.

7. Progress UX If total size is known (you supply file sizes), the response can carry Content-Length, and the browser/JS client can render a real progress bar (onDownloadProgress in axios/fetch). Without sizes, progress is indeterminate — plan your UI accordingly.

8. Testing Feature tests can assert status and headers (Content-Disposition, Content-Type). To verify contents, saveTo() a tempnam() file, open with ZipArchive, and assert entry names. For streamed responses, $response->streamedContent() works in Laravel's test helpers, but assertDownload() behavior varies by version.


Gotchas and Tips

  • Nothing may echo before the stream. Whitespace after ?>, a BOM, a stray dd(), or a debug toolbar's ob_start will corrupt the ZIP. Exclude the download route from Debugbar/Telescope and any middleware that mutates response bodies.
  • StreamedResponse bypasses some middleware. Content-rewriting middleware (compression, minifiers, CSP nonce injectors) can break the archive. Prefer a dedicated route group for downloads.
  • Unknown size = no Content-Length. The ZIP central directory is written last, so the total isn't known unless the library is told each file's size. Pass sizes where the API supports it when accurate progress or non-chunked responses matter.
  • Compression choice matters. STORE (no compression) for already-compressed payloads — JPEG, MP4, PDFs, nested ZIPs — saves significant CPU and speeds up the stream. DEFLATE for text/CSV/JSON. Compression level is configurable on create().
  • ZIP64 for very large archives. Files/archives over ~4 GB (or >65k entries) require ZIP64. Confirm your zipstream-php version enables it and that the client's unzip tool supports it.
  • Duplicate basenames collide. Two report.pdf files from different directories can confuse extractors. Set explicit filenames via the per-file name argument/option.
  • PHP/nginx timeouts still apply. A slow S3-backed archive can hit max_execution_time or fastcgi_read_timeout. Bump limits for the export route, or move to the queue pattern.
  • Config/version drift. Publish config/zipstream.php (if your version ships one) to tune default filename and headers; remember to re-publish after major upgrades. v2 → v3 changed the API shape (create/facade + sources), so pin a version and read the matching docs.
  • Extension points. Custom Source implementations (when exposed) are the clean way to plug in arbitrary backends; container-bind your own exporter subclass if you need organization-specific defaults without forking.
  • Verifying output locally. When debugging, saveTo('/tmp/test.zip') and unzip — this isolates archive-building bugs from HTTP/streaming bugs much faster than inspecting headers.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console