PHPackages                             stechstudio/laravel-zipstream - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [File &amp; Storage](/categories/file-storage)
4. /
5. stechstudio/laravel-zipstream

ActiveLibrary[File &amp; Storage](/categories/file-storage)

stechstudio/laravel-zipstream
=============================

A fast and simple streaming zip file downloader for Laravel.

5.10(2mo ago)4633.7M↑11.8%632MITPHPPHP ^8.1CI passing

Since Apr 12Pushed 2mo ago7 watchersCompare

[ Source](https://github.com/stechstudio/laravel-zipstream)[ Packagist](https://packagist.org/packages/stechstudio/laravel-zipstream)[ Docs](https://github.com/stechstudio/laravel-zipstream)[ RSS](/packages/stechstudio-laravel-zipstream/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (10)Dependencies (20)Versions (55)Used By (2)

Streaming Zips with Laravel
===========================

[](#streaming-zips-with-laravel)

[![Latest Version on Packagist](https://camo.githubusercontent.com/7916a3f0c4bd66b21c33a0599fff7b56a6b9c2919bd97235929de5862db47ddf/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f737465636873747564696f2f6c61726176656c2d7a697073747265616d2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/stechstudio/laravel-zipstream)[![Total Downloads](https://camo.githubusercontent.com/3f9099b9f0245ac3f13ef1fea92d04e0a6a1ba4618401947cf8c7c4924912f80/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f737465636873747564696f2f6c61726176656c2d7a697073747265616d2e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/stechstudio/laravel-zipstream)[![Software License](https://camo.githubusercontent.com/55c0218c8f8009f06ad4ddae837ddd05301481fcf0dff8e0ed9dadda8780713e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d627269676874677265656e2e7376673f7374796c653d666c61742d737175617265)](LICENSE.md)[![Tests](https://github.com/stechstudio/laravel-zipstream/actions/workflows/tests.yml/badge.svg)](https://github.com/stechstudio/laravel-zipstream/actions/workflows/tests.yml)

A fast and simple streaming zip file downloader for Laravel.

- Builds zip files from local or S3 file sources, or any other PSR7 stream.
- Provides a direct download stream to your user. The zip download begins immediately even though the zip is still being created. No need to save the zip to disk first.
- Calculates the zip filesize up front for the `Content-Length` header. The user gets an accurate download time estimate in their browser.
- Built on top of the excellent [ZipStream-PHP](https://github.com/maennchen/ZipStream-PHP) library.

Upgrading
---------

[](#upgrading)

Upgrading from version 4? Make sure to look at the release notes for version 5. There are some breaking changes.

Quickstart
----------

[](#quickstart)

#### 1. Install the package

[](#1-install-the-package)

```
composer require stechstudio/laravel-zipstream
```

The service provider and facade will be automatically wired up.

#### 2. In a controller method call the `create` method on the `Zip` facade

[](#2-in-a-controller-method-call-the-create-method-on-the-zip-facade)

```
use STS\ZipStream\Facades\Zip;

class ZipController {

    public function build()
    {
        return Zip::create("package.zip", [
            "/path/to/Some File.pdf",
            "/path/to/Export.xlsx"
        ]);
    }
}
```

That's it! A `StreamedResponse` will be returned and the zip contents built and streamed out. The user's browser will begin downloading a `package.zip` file immediately.

Customize the internal zip path for a file
------------------------------------------

[](#customize-the-internal-zip-path-for-a-file)

By default, any files you add will be stored in the root of the zip, with their original filenames.

You can customize the filename and even create sub-folders within the zip by providing your files array with key/value pairs:

```
Zip::create("package.zip", [

    // Will be stored as `Some File.pdf` in the zip
    "/path/to/Some File.pdf",

    // Will be stored as `Export.xlsx` in the zip
    "/path/to/data.xlsx" => 'Export.xlsx',

    // Will create a `log` subfolder in the zip and be stored as `log/details.txt`
    "/path/to/log.txt" => "log/details.txt"

]);
```

Fluent usage
------------

[](#fluent-usage)

You can also provide your files one at a time:

```
Zip::create("package.zip")
    ->add("/path/to/Some File.pdf")
    ->add("/path/to/data.xlsx", 'Export.xlsx')
    ->add("/path/to/log.txt", "log/details.txt");
```

Add HTTP file sources
---------------------

[](#add-http-file-sources)

You can add HTTP URLs as the source filepath. Note that zip filesize can only be calculated up front if the HTTP source provides a `Content-Length` header, not all URLs do.

```
Zip::create("package.zip")
    ->add("https://...", "myfile.pdf");
```

Add raw file data
-----------------

[](#add-raw-file-data)

You can provide raw data instead of a filepath:

```
Zip::create("package.zip")
    ->addRaw("...file contents...", "hello.txt");
```

Add from storage disk
---------------------

[](#add-from-storage-disk)

You can add files from a storage disk. Use `addFromDisk` and provide the disk name or disk instance as the first argument:

```
Zip::create("package.zip")
    ->addFromDisk("local", "file.txt", "My File.txt")
    ->addFromDisk(Storage::disk("tmp"), "important.txt")
```

Support for S3
--------------

[](#support-for-s3)

### Install AWS sdk and configure S3

[](#install-aws-sdk-and-configure-s3)

You can stream files from S3 into your zip.

1. Install the `aws/aws-sdk-php` package
2. Set up an AWS IAM user with `s3:GetObject` permission for the S3 bucket and objects you intend to zip up.
3. Store your credentials as `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, and `AWS_DEFAULT_REGION` in your .env file.

### Add S3 files to your zip

[](#add-s3-files-to-your-zip)

Provide `s3://` paths when creating the zip:

```
Zip::create("package.zip")
    ->add("s3://bucket-name/path/to/object.pdf", "Something.pdf");
```

By default, this package will try to create an S3 client using the same .env file credentials that Laravel uses. If needed, you can wire up a custom S3 client to the `zipstream.s3client` container key. Or you can even pass in your own S3 client when adding a file to the zip. To do this, you'll need to create an `S3File` model instance yourself so that you can provide the client, like this:

```
use STS\ZipStream\Models\S3File;

// Create your own client however necessary
$s3 = new Aws\S3\S3Client();

Zip::create("package.zip")->add(
    S3File::make("s3://bucket-name/path/to/object.pdf")->setS3Client($s3)
);
```

Instead of specifying an absolute `s3://` path, you can use `addFromDisk` and specify a disk that uses the `s3` driver:

```
Zip::create("package.zip")
    ->addFromDisk("s3", "object.pdf", "Something.pdf");
```

In this case the S3 client from the storage disk will be used.

Specify your own filesizes
--------------------------

[](#specify-your-own-filesizes)

It can be expensive retrieving filesizes for some file sources such as S3 or HTTP. These require dedicated calls, and can add up to a lot of time if you are zipping up many files. If you store filesizes in your database and have them available, you can drastically improve performance by providing filesizes when you add files. You'll need to make your own File models instead of adding paths directly to the zip.

Let's say you have a collection of Eloquent `$files`, are looping through and building a zip. If you have a `filesize` attribute available, it would look something like this:

```
use STS\ZipStream\Models\File;

// Retrieve file records from the database
$files = ...;

$zip = Zip::create("package.zip");

foreach($files AS $file) {
    $zip->add(
        File::make($file->path, $file->name)->setFilesize($file->size)
    );
}
```

Or if you are adding from an S3 disk:

```
$zip->add(
    File::makeFromDisk('s3', $file->key, $file->name)->setFilesize($file->size)
);
```

Zip size prediction
-------------------

[](#zip-size-prediction)

By default, this package attempts to predict the final zip size and sends a `Content-Length` header up front. This means users will see accurate progress on their download, even though the zip is being streamed out as it is created!

This only works if files are not compressed.

If you have issues with the zip size prediction you can disable it with `ZIPSTREAM_PREDICT_SIZE=false` in your .env file.

Configure compression
---------------------

[](#configure-compression)

By default, this package uses *no* compression. Why?

1. This makes building the zips super fast, and is light on your CPU
2. This makes it possible to predict the final zip size as mentioned above.

If you want to compress your zip files set `ZIPSTREAM_COMPRESSION_METHOD=deflate` in your .env file. Just realize this will disable the `Content-Length` header.

Configure conflict strategy
---------------------------

[](#configure-conflict-strategy)

If two or more files are added to the zip with the same zip path, you can use `ZIPSTREAM_CONFLICT_STRATEGY` to configure how the conflict is handled:

- `ZIPSTREAM_CONFLICT_STRATEGY=skip`: Keep the initial file, skip adding the conflicting file (default)
- `ZIPSTREAM_CONFLICT_STRATEGY=replace`: Keep the latest file, overwrite previous files at the same path
- `ZIPSTREAM_CONFLICT_STRATEGY=rename`: Append a number to the conflicting file name, e.g. `file.txt` becomes `file_1.txt`

Note: filenames are compared case-insensitive. `FILE.txt` and `file.TXT` are considered conflicting. If you are working only on a case-sensitive filesystem you can set `ZIPSTREAM_CASE_INSENSITIVE_CONFLICTS=false`. Don't do this if you have Windows users opening your zips!

Save Zip to disk
----------------

[](#save-zip-to-disk)

Even though the primary goal of this package is to enable zip downloads without saving to disk, there may be times you'd like to generate a zip on disk as well. And you might as well make use of this package to do so.

Use the `saveTo` method to write the entire zip to disk immediately. Note that this expects a folder path, the zip name will be appended.

```
Zip::create("package.zip")
    // ... add files ...
    ->saveTo("/path/to/folder");
```

And yes, if you've properly setup and configured S3 you can even save to an S3 bucket/path.

```
Zip::create("package.zip")
    // ... add files ...
    ->saveTo("s3://bucket-name/path/to/folder");
```

Or you can save to a disk:

```
Zip::create("package.zip")
    // ... add files ...
    ->saveToDisk("s3", "folder");
```

Warning

S3 has a limit of 5GB when objects are saved using a stream the way we are doing. Saving your zip to S3 will fail if it is over this limit. If this is an issue for your use-case, we recommend saving to local disk first and then separately using the S3 SDK to store the file using multipart.

Caching zip while still streaming download
------------------------------------------

[](#caching-zip-while-still-streaming-download)

What if you have a lot of users requesting the same zip payload? It might be nice to stream out the zip while *also* caching it to disk for the future.

Use the `cache` method to provide a cache path. Note this should be the entire path including filename.

```
Zip::create("package.zip")
    // ... add files ...
    ->cache("/path/to/folder/some-unique-cache-name.zip");
```

Or you can cache to a disk:

```
Zip::create("package.zip")
    // ... add files ...
    ->cacheToDisk("s3", "folder/some-unique-cache-name.zip");
```

You might use an internal DB id for your cache name, so that the next time a user requests a zip download you can determine if one is already built and just hand it back.

Events
------

[](#events)

- `STS\ZipStream\Events\ZipStreaming`: Dispatched when a new zip stream begins processing
- `STS\ZipStream\Events\ZipStreamed`: Dispatched when a zip finishes streaming

Custom file types
-----------------

[](#custom-file-types)

This package supports local files, S3, and HTTP URLs out of the box. If you need to support additional file sources (FTP, SFTP, encrypted filesystems, etc.), you can register your own file type.

Create a class that extends `STS\ZipStream\Models\File` and implement the required methods:

```
use GuzzleHttp\Psr7\Utils;
use Illuminate\Filesystem\FilesystemAdapter;
use Psr\Http\Message\StreamInterface;
use STS\ZipStream\Models\File;
use STS\ZipStream\OutputStream;

class FtpFile extends File
{
    public static function supports(string $source): bool
    {
        return str_starts_with($source, 'ftp://') || str_starts_with($source, 'ftps://');
    }

    public static function supportsDisk(FilesystemAdapter $disk): bool
    {
        // Return true if this type can handle the given disk adapter
        return $disk->getAdapter() instanceof \League\Flysystem\Ftp\FtpAdapter;
    }

    protected function buildReadableStream(): StreamInterface
    {
        return Utils::streamFor(fopen($this->source, 'rb'));
    }

    protected function buildWritableStream(): OutputStream
    {
        return new OutputStream(fopen($this->source, 'wb'));
    }

    public function calculateFilesize(): int
    {
        return filesize($this->source);
    }

    public function canPredictZipDataSize(): bool
    {
        return true;
    }
}
```

Then register it in a service provider:

```
use STS\ZipStream\Facades\Zip;

public function boot()
{
    Zip::extend(FtpFile::class);
}
```

Your custom type will be checked before the built-in types, so you can even override default behavior by matching the same source patterns.

Filename sanitization
---------------------

[](#filename-sanitization)

By default, this package will try to translate any non-ascii character in filename or folder's name to ascii. For example, if your filename is `中文_にほんご_Ч_Ɯ_☺_someascii.txt`. It will become `__C___someascii.txt` using Laravel's `Str::ascii($path)`.

If you need to preserve non-ascii characters, you can disable this feature with an `.env` setting:

```
ZIPSTREAM_ASCII_FILENAMES=false
```

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

71

—

ExcellentBetter than 100% of packages

Maintenance88

Actively maintained with recent releases

Popularity65

Solid adoption and visibility

Community31

Small or concentrated contributor base

Maturity82

Battle-tested with a long release history

 Bus Factor1

Top contributor holds 75.5% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~49 days

Recently: every ~59 days

Total

52

Last Release

62d ago

Major Versions

1.7 → 2.02019-11-22

2.6.1 → 3.02020-11-13

3.2 → 4.02021-01-25

4.x-dev → 5.0-beta2024-07-05

PHP version history (3 changes)1.0PHP ^7.1

3.1PHP ^7.1|^8.0

5.0-betaPHP ^8.1

### Community

Maintainers

![](https://www.gravatar.com/avatar/315be5f111b5501a41b99a0205c9c85915335391168a0ed10316546a1a38bbd8?d=identicon)[jszobody](/maintainers/jszobody)

---

Top Contributors

[![jszobody](https://avatars.githubusercontent.com/u/203749?v=4)](https://github.com/jszobody "jszobody (74 commits)")[![laravel-shift](https://avatars.githubusercontent.com/u/15991828?v=4)](https://github.com/laravel-shift "laravel-shift (4 commits)")[![toto4ds](https://avatars.githubusercontent.com/u/5242888?v=4)](https://github.com/toto4ds "toto4ds (4 commits)")[![Firtzberg](https://avatars.githubusercontent.com/u/8490119?v=4)](https://github.com/Firtzberg "Firtzberg (3 commits)")[![miraries](https://avatars.githubusercontent.com/u/4648498?v=4)](https://github.com/miraries "miraries (2 commits)")[![it-can](https://avatars.githubusercontent.com/u/644288?v=4)](https://github.com/it-can "it-can (2 commits)")[![andreacivita](https://avatars.githubusercontent.com/u/4959092?v=4)](https://github.com/andreacivita "andreacivita (1 commits)")[![ryangjchandler](https://avatars.githubusercontent.com/u/41837763?v=4)](https://github.com/ryangjchandler "ryangjchandler (1 commits)")[![TaiYou-TW](https://avatars.githubusercontent.com/u/16871628?v=4)](https://github.com/TaiYou-TW "TaiYou-TW (1 commits)")[![hAz5](https://avatars.githubusercontent.com/u/14108756?v=4)](https://github.com/hAz5 "hAz5 (1 commits)")[![bayprogrammer](https://avatars.githubusercontent.com/u/957810?v=4)](https://github.com/bayprogrammer "bayprogrammer (1 commits)")[![cyreb7](https://avatars.githubusercontent.com/u/1165781?v=4)](https://github.com/cyreb7 "cyreb7 (1 commits)")[![dp88](https://avatars.githubusercontent.com/u/3003563?v=4)](https://github.com/dp88 "dp88 (1 commits)")[![fillmoreb](https://avatars.githubusercontent.com/u/5767446?v=4)](https://github.com/fillmoreb "fillmoreb (1 commits)")[![GITSKayDomrose](https://avatars.githubusercontent.com/u/51118008?v=4)](https://github.com/GITSKayDomrose "GITSKayDomrose (1 commits)")

---

Tags

laravelstreamingstreaming-zipzipstechstudiolaravel-zipstream

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/stechstudio-laravel-zipstream/health.svg)

```
[![Health](https://phpackages.com/badges/stechstudio-laravel-zipstream/health.svg)](https://phpackages.com/packages/stechstudio-laravel-zipstream)
```

###  Alternatives

[aws/aws-sdk-php

AWS SDK for PHP - Use Amazon Web Services in your PHP project

6.2k511.3M2.2k](/packages/aws-aws-sdk-php)[google/cloud

Google Cloud Client Library

1.2k16.2M53](/packages/google-cloud)[sylius/sylius

E-Commerce platform for PHP, based on Symfony framework.

8.4k5.6M651](/packages/sylius-sylius)[kreait/firebase-php

Firebase Admin SDK

2.4k39.7M72](/packages/kreait-firebase-php)[google/cloud-core

Google Cloud PHP shared dependency, providing functionality useful to all components.

343121.4M79](/packages/google-cloud-core)[spatie/laravel-export

Create a static site bundle from a Laravel app

646127.9k5](/packages/spatie-laravel-export)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
