Skip to content

Commit cb81e43

Browse files
authored
Version 5 (#115)
* heavily refactored for zipstream 3.1 * docs * create our own stream wrapper for caching output to secondary stream * underlying package handles size estimation now, we don’t need these * improvements for our wrapped caching output stream, with test * comments * more cache output options supported * some cleanup * Support for a callback to run after zip stream is finished * Support for a `$zip->has($path)` check. Resolves #97 * Support adding files from Laravel Storage disks * update docs * update docs * update docs * Support saving output to disk * update docs * update docs * remove this header from the streamed response * flush output, minimize buffering and RAM usage * add the nginx buffering header here * getOption method in the File model * don’t exclude any tests now * run tests on php8.3 * s3 client requires a region
1 parent 5e442e7 commit cb81e43

31 files changed

+722
-1078
lines changed

.chipperci.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
version: 1
22

33
environment:
4-
php: 8.1 # 7.1, 7.2, 7.3, 7.4, 8.0, 8.1
4+
php: 8.3 # 7.1, 7.2, 7.3, 7.4, 8.0, 8.1
55

66
pipeline:
77
- name: Setup
88
cmd: |
99
composer install --no-interaction --prefer-dist --optimize-autoloader
1010
1111
- name: Run Tests
12-
cmd: phpunit --exclude big
12+
cmd: phpunit

README.md

Lines changed: 57 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ The service provider and facade will be automatically wired up.
2525
#### 2. In a controller method call the `create` method on the `Zip` facade
2626

2727
```php
28-
use Zip;
28+
use STS\ZipStream\Facades\Zip;
2929

3030
class ZipController {
3131

@@ -43,9 +43,9 @@ That's it! A `StreamedResponse` will be returned and the zip contents built and
4343

4444
## Customize the internal zip path for a file
4545

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

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

5050
```php
5151
Zip::create("package.zip", [
@@ -91,6 +91,16 @@ Zip::create("package.zip")
9191
->addRaw("...file contents...", "hello.txt");
9292
```
9393

94+
## Add from storage disk
95+
96+
You can add files from a storage disk. Use `addFromDisk` and provide the disk name or disk instance as the first argument:
97+
98+
```php
99+
Zip::create("package.zip")
100+
->addFromDisk("local", "file.txt", "My File.txt")
101+
->addFromDisk(Storage::disk("tmp"), "important.txt")
102+
```
103+
94104
## Support for S3
95105

96106
### Install AWS sdk and configure S3
@@ -99,7 +109,7 @@ You can stream files from S3 into your zip.
99109

100110
1. Install the `aws/aws-sdk-php` package
101111

102-
2. Setup an AWS IAM user with `s3:GetObject` permission for the S3 bucket and objects you intend to zip up.
112+
2. Set up an AWS IAM user with `s3:GetObject` permission for the S3 bucket and objects you intend to zip up.
103113

104114
3. Store your credentials as `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, and `AWS_DEFAULT_REGION` in your .env file.
105115

@@ -125,13 +135,14 @@ Zip::create("package.zip")->add(
125135
);
126136
```
127137

128-
## Zip size prediction
129-
130-
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!
138+
Instead of specifying an absolute `s3://` path, you can use `addFromDisk` and specify a disk that uses the `s3` driver:
131139

132-
This only works if files are not compressed.
140+
```php
141+
Zip::create("package.zip")
142+
->addFromDisk("s3", "object.pdf", "Something.pdf");
143+
```
133144

134-
If you have issues with the zip size prediction you can disable it with `ZIPSTREAM_PREDICT_SIZE=false` in your .env file.
145+
In this case the S3 client from the storage disk will be used.
135146

136147
## Specify your own filesizes
137148

@@ -154,14 +165,30 @@ foreach($files AS $file) {
154165
}
155166
```
156167

168+
Or if you are adding from an S3 disk:
169+
170+
```php
171+
$zip->add(
172+
File::makeFromDisk('s3', $file->key, $file->name)->setFilesize($file->size)
173+
);
174+
````
175+
176+
## Zip size prediction
177+
178+
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!
179+
180+
This only works if files are not compressed.
181+
182+
If you have issues with the zip size prediction you can disable it with `ZIPSTREAM_PREDICT_SIZE=false` in your .env file.
183+
157184
## Configure compression
158185

159-
By default this package uses _no_ compression. Why?
186+
By default, this package uses _no_ compression. Why?
160187

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

164-
If you want to compress your zip files set `ZIPSTREAM_FILE_METHOD=deflate` in your .env file. Just realize this will disable the `Content-Length` header.
191+
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.
165192

166193
## Save Zip to disk
167194

@@ -183,6 +210,14 @@ Zip::create("package.zip")
183210
->saveTo("s3://bucket-name/path/to/folder");
184211
```
185212

213+
Or you can save to a disk:
214+
215+
```php
216+
Zip::create("package.zip")
217+
// ... add files ...
218+
->saveToDisk("s3", "folder");
219+
```
220+
186221
## Caching zip while still streaming download
187222

188223
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.
@@ -195,22 +230,29 @@ Zip::create("package.zip")
195230
->cache("/path/to/folder/some-unique-cache-name.zip");
196231
```
197232

233+
Or you can cache to a disk:
234+
235+
```php
236+
Zip::create("package.zip")
237+
// ... add files ...
238+
->cacheToDisk("s3", "folder/some-unique-cache-name.zip");
239+
```
240+
198241
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.
199242

200243
## Events
201244

202245
- `STS\ZipStream\Events\ZipStreaming`: Dispatched when a new zip stream begins processing
203-
- `STS\ZipStream\Events\ZipStreamed`: Dispatched when a zip finishes streaming
204-
- `STS\ZipStream\Events\ZipSizePredictionFailed`: Fired if the predicted filesize doesn't match the final size. If you have filesize prediction enabled it's a good idea to listen for this event and log it, since that might mean the zip download failed or was corrupt for your user.
246+
- `STS\ZipStream\Events\ZipStreamed`: Dispatched when a zip finishes streaming
205247

206248
## Filename sanitization
207249

208-
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)`.
250+
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)`.
209251

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

212254
```env
213-
ZIPSTREAM_FILE_SANITIZE=false
255+
ZIPSTREAM_ASCII_FILENAMES=false
214256
```
215257

216258
## License

composer.json

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,19 @@
1515
}
1616
],
1717
"require": {
18-
"php": "^7.1|^8.0",
19-
"guzzlehttp/guzzle": "^6.0|^7.0",
20-
"illuminate/support": "^5.6|^6.0|^7.0|^8.0|^9.0|^10.0|^11.0",
21-
"maennchen/zipstream-php": "^v2.0"
18+
"php": "^8.1",
19+
"guzzlehttp/guzzle": "^7.0",
20+
"guzzlehttp/psr7": "^2.6",
21+
"illuminate/support": "^10.0|^11.0",
22+
"league/flysystem-path-prefixing": "^3.28",
23+
"maennchen/zipstream-php": "^v3.0",
24+
"psr/http-message": "^2.0",
25+
"spatie/laravel-package-tools": "^1.16"
2226
},
2327
"require-dev": {
24-
"orchestra/testbench": "^5.0|^6.0|^7.0|^8.0|^9.0",
25-
"phpunit/phpunit": "^9.0"
28+
"league/flysystem-aws-s3-v3": "^3.28",
29+
"orchestra/testbench": "^8.0|^9.0",
30+
"phpunit/phpunit": "^9.0|^10.0"
2631
},
2732
"autoload": {
2833
"psr-4": {
@@ -47,7 +52,7 @@
4752
"STS\\ZipStream\\ZipStreamServiceProvider"
4853
],
4954
"aliases": {
50-
"Zip": "STS\\ZipStream\\ZipStreamFacade"
55+
"Zip": "STS\\ZipStream\\Facades\\Zip"
5156
}
5257
}
5358
}

config/config.php renamed to config/zipstream.php

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,15 @@
11
<?php
2+
use ZipStream\CompressionMethod;
23

3-
/*
4-
* You can place your custom package configuration in here.
5-
*/
64
return [
7-
// Default options for our archives
8-
'archive' => [
9-
'predict' => env('ZIPSTREAM_PREDICT_SIZE', true)
10-
],
11-
12-
// Default options for files added
13-
'file' => [
14-
'method' => env('ZIPSTREAM_FILE_METHOD', 'store'),
5+
// Try to predict the zip size up front and send a Content-Length header
6+
'predict_size' => env('ZIPSTREAM_PREDICT_SIZE', true),
157

16-
'deflate' => env('ZIPSTREAM_FILE_DEFLATE'),
8+
// Compression method used only if we don't (or can't) predict the zip size
9+
'compression_method' => env('ZIPSTREAM_COMPRESSION_METHOD', 'store'),
1710

18-
'sanitize' => env('ZIPSTREAM_FILE_SANITIZE', true)
19-
],
11+
// Remove all non-ascii characters from filenames
12+
'ascii_filenames' => env('ZIPSTREAM_ASCII_FILENAMES', true),
2013

2114
// AWS configs for S3 files
2215
'aws' => [

phpunit.xml.dist

Lines changed: 11 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,13 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3-
bootstrap="vendor/autoload.php"
4-
backupGlobals="false"
5-
backupStaticAttributes="false"
6-
colors="true"
7-
verbose="true"
8-
convertErrorsToExceptions="true"
9-
convertNoticesToExceptions="true"
10-
convertWarningsToExceptions="true"
11-
processIsolation="false"
12-
stopOnFailure="false"
13-
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd">
14-
<coverage>
15-
<include>
16-
<directory suffix=".php">src/</directory>
17-
</include>
18-
</coverage>
19-
<testsuites>
20-
<testsuite name="Test Suite">
21-
<directory>tests</directory>
22-
</testsuite>
23-
</testsuites>
2+
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" bootstrap="vendor/autoload.php" backupGlobals="false" colors="true" processIsolation="false" stopOnFailure="false" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd" cacheDirectory=".phpunit.cache" backupStaticProperties="false">
3+
<testsuites>
4+
<testsuite name="Test Suite">
5+
<directory>tests</directory>
6+
</testsuite>
7+
</testsuites>
8+
<source>
9+
<include>
10+
<directory suffix=".php">src/</directory>
11+
</include>
12+
</source>
2413
</phpunit>

0 commit comments

Comments
 (0)