diff --git a/config/config.php b/config/config.php index df957c9..bd134c0 100755 --- a/config/config.php +++ b/config/config.php @@ -6,8 +6,6 @@ return [ // Default options for our archives 'archive' => [ - 'zip64' => env('ZIPSTREAM_ENABLE_ZIP64', true), - 'predict' => env('ZIPSTREAM_PREDICT_SIZE', true) ], diff --git a/src/ZipStream.php b/src/ZipStream.php index c80c827..64d1e8d 100755 --- a/src/ZipStream.php +++ b/src/ZipStream.php @@ -160,15 +160,15 @@ public function getMeta(): Collection public function process(): int { $this->bytesSent = 0; + $this->configureZip64(); event(new ZipStreaming($this)); - $this->queue->map->toZipStreamFile($this)->each->process(); - $predicted = $this->canPredictZipSize() ? $this->predictZipSize() : false; + $this->queue->map->toZipStreamFile($this)->each->process(); $this->finish(); $this->getOutputStream()->close(); @@ -178,13 +178,23 @@ public function process(): int event(new ZipStreamed($this)); - if ($predicted && $predicted != $this->getFinalSize()) { + if ($predicted !== false && $predicted != $this->getFinalSize()) { event(new ZipSizePredictionFailed($this, $predicted, $this->getFinalSize())); } return $this->getFinalSize(); } + public function configureZip64() + { + $this->opt->setEnableZip64( + // More than 65535 files + count($this->files) > 0xFFFF + // Filesize over max 32 bit integer + || $this->queue->sum->getFilesize() > 0xFFFFFFFF + ); + } + /** * @return StreamedResponse */ @@ -324,17 +334,33 @@ public function predictZipSize(): int return $this->predictedSize; } + $this->configureZip64(); + $this->predictedSize = $this->calculateZipSize(); + + // It's conceivable that we didn't need Zip64 until the zip headers/decriptors were added. + // If so, turn on Zip64 and calculate again. + if(!$this->opt->isEnableZip64() && $this->predictedSize > 0xFFFFFFFF) { + $this->opt->setEnableZip64(true); + $this->predictedSize = $this->calculateZipSize(); + } + + return $this->predictedSize; + } + + /** + * @return int + */ + protected function calculateZipSize(): int + { $this->bytesSent = 0; $this->calculateOnly = true; $this->queue->map->toZipStreamFile($this)->each->calculate(); $this->finish(); - $this->predictedSize = $this->queue->sum->getFilesize() + $this->getFinalSize(); - $this->calculateOnly = false; - return $this->predictedSize; + return $this->queue->sum->getFilesize() + $this->getFinalSize(); } /** diff --git a/src/ZipStreamServiceProvider.php b/src/ZipStreamServiceProvider.php index d5f08e1..21e5bc2 100755 --- a/src/ZipStreamServiceProvider.php +++ b/src/ZipStreamServiceProvider.php @@ -55,7 +55,6 @@ public function provides() protected function buildArchiveOptions(array $config) { return tap(new ArchiveOptions(), function(ArchiveOptions $options) use($config) { - $options->setEnableZip64($config['zip64']); $options->setZeroHeader(true); }); } diff --git a/tests/ZipTest.php b/tests/ZipTest.php index 7a2092b..1afe369 100644 --- a/tests/ZipTest.php +++ b/tests/ZipTest.php @@ -29,17 +29,18 @@ public function testSaveZipOutput() file_put_contents("/tmp/test2.txt", "this is the second test file for test run $testrun"); /** @var ZipStream $zip */ - $zip = Zip::create("my.zip", ["/tmp/test1.txt", "/tmp/test2.txt"]); + $zip = Zip::create("small.zip", ["/tmp/test1.txt", "/tmp/test2.txt"]); $sizePrediction = $zip->predictZipSize(); $zip->saveTo("/tmp"); - $this->assertTrue(file_exists("/tmp/my.zip")); - $this->assertEquals($sizePrediction, filesize("/tmp/my.zip")); + $this->assertFalse($zip->opt->isEnableZip64()); + $this->assertTrue(file_exists("/tmp/small.zip")); + $this->assertEquals($sizePrediction, filesize("/tmp/small.zip")); - $z = zip_open("/tmp/my.zip"); + $z = zip_open("/tmp/small.zip"); $this->assertEquals("this is the first test file for test run $testrun", zip_entry_read(zip_read($z))); - unlink("/tmp/my.zip"); + unlink("/tmp/small.zip"); } public function testSaveZip64Output() @@ -51,16 +52,17 @@ public function testSaveZip64Output() exec('dd if=/dev/zero count=1024 bs=1048576 >/tmp/medfile.txt'); /** @var ZipStream $zip */ - $zip = Zip::create("my.zip", ["/tmp/test1.txt", "/tmp/test2.txt", "/tmp/bigfile.txt", "/tmp/medfile.txt"]); + $zip = Zip::create("large.zip", ["/tmp/test1.txt", "/tmp/test2.txt", "/tmp/bigfile.txt", "/tmp/medfile.txt"]); $sizePrediction = $zip->predictZipSize(); $zip->saveTo("/tmp"); - $this->assertTrue(file_exists("/tmp/my.zip")); - $this->assertEquals($sizePrediction, filesize("/tmp/my.zip")); + $this->assertTrue($zip->opt->isEnableZip64()); + $this->assertTrue(file_exists("/tmp/large.zip")); + $this->assertEquals($sizePrediction, filesize("/tmp/large.zip")); - $z = zip_open("/tmp/my.zip"); + $z = zip_open("/tmp/large.zip"); $this->assertEquals("this is the first test file for test run $testrun", zip_entry_read(zip_read($z))); - unlink("/tmp/my.zip"); + unlink("/tmp/large.zip"); } } \ No newline at end of file