changes for filter and print

This commit is contained in:
2024-09-29 16:59:27 +05:45
parent 497f567cba
commit 684e01bf48
1335 changed files with 38709 additions and 74987 deletions

View File

@ -1,79 +1,47 @@
Adding Content-Length header
=============
Adding a ``Content-Length`` header for ``ZipStream`` is not trivial since the
size is not known beforehand.
Adding a ``Content-Length`` header for ``ZipStream`` can be achieved by
using the options ``SIMULATION_STRICT`` or ``SIMULATION_LAX`` in the
``operationMode`` parameter.
The following workaround adds an approximated header:
In the ``SIMULATION_STRICT`` mode, ``ZipStream`` will not allow to calculate the
size based on reading the whole file. ``SIMULATION_LAX`` will read the whole
file if neccessary.
``SIMULATION_STRICT`` is therefore useful to make sure that the size can be
calculated efficiently.
.. code-block:: php
use ZipStream\OperationMode;
use ZipStream\ZipStream;
class Zip
{
/** @var string */
private $name;
$zip = new ZipStream(
operationMode: OperationMode::SIMULATE_STRICT, // or SIMULATE_LAX
defaultEnableZeroHeader: false,
sendHttpHeaders: true,
outputStream: $stream,
);
private $files = [];
// Normally add files
$zip->addFile('sample.txt', 'Sample String Data');
public function __construct($name)
{
$this->name = $name;
// Use addFileFromCallback and exactSize if you want to defer opening of
// the file resource
$zip->addFileFromCallback(
'sample.txt',
exactSize: 18,
callback: function () {
return fopen('...');
}
);
public function addFile($name, $data)
{
$this->files[] = ['type' => 'addFile', 'name' => $name, 'data' => $data];
}
// Read resulting file size
$size = $zip->finish();
// Tell it to the browser
header('Content-Length: '. $size);
// Execute the Simulation and stream the actual zip to the client
$zip->executeSimulation();
public function addFileFromPath($name, $path)
{
$this->files[] = ['type' => 'addFileFromPath', 'name' => $name, 'path' => $path];
}
public function getEstimate()
{
$estimate = 22;
foreach ($this->files as $file) {
$estimate += 76 + 2 * strlen($file['name']);
if ($file['type'] === 'addFile') {
$estimate += strlen($file['data']);
}
if ($file['type'] === 'addFileFromPath') {
$estimate += filesize($file['path']);
}
}
return $estimate;
}
public function finish()
{
header('Content-Length: ' . $this->getEstimate());
$options = new \ZipStream\Option\Archive();
$options->setSendHttpHeaders(true);
$options->setEnableZip64(false);
$options->setDeflateLevel(-1);
$zip = new \ZipStream\ZipStream($this->name, $options);
$fileOptions = new \ZipStream\Option\File();
$fileOptions->setMethod(\ZipStream\Option\Method::STORE());
foreach ($this->files as $file) {
if ($file['type'] === 'addFile') {
$zip->addFile($file['name'], $file['data'], $fileOptions);
}
if ($file['type'] === 'addFileFromPath') {
$zip->addFileFromPath($file['name'], $file['path'], $fileOptions);
}
}
$zip->finish();
exit;
}
}
It only works with the following constraints:
- All file content is known beforehand.
- Content Deflation is disabled
Thanks to
`partiellkorrekt <https://github.com/maennchen/ZipStream-PHP/issues/89#issuecomment-1047949274>`_
for this workaround.

View File

@ -14,20 +14,21 @@ default one, and pass it to Flysystem ``putStream`` method.
// the content is lost when closing the stream / opening another one
$tempStream = fopen('php://memory', 'w+');
// Init Options
$zipStreamOptions = new Archive();
$zipStreamOptions->setOutputStream($tempStream);
// Create Zip Archive
$zipStream = new ZipStream('test.zip', $zipStreamOptions);
$zipStream = new ZipStream(
outputStream: $tempStream,
outputName: 'test.zip',
);
$zipStream->addFile('test.txt', 'text');
$zipStream->finish();
// Store File (see Flysystem documentation, and all its framework integration)
$adapter = new Local(__DIR__.'/path/to/folder'); // Can be any adapter (AWS, Google, Ftp, etc.)
// Store File
// (see Flysystem documentation, and all its framework integration)
// Can be any adapter (AWS, Google, Ftp, etc.)
$adapter = new Local(__DIR__.'/path/to/folder');
$filesystem = new Filesystem($adapter);
$filesystem->putStream('test.zip', $tempStream)
$filesystem->writeStream('test.zip', $tempStream)
// Close Stream
fclose($tempStream);
fclose($tempStream);

View File

@ -2,60 +2,65 @@ Available options
===============
Here is the full list of options available to you. You can also have a look at
``src/Option/Archive.php`` file.
First, an instance of ``ZipStream\Option\Archive`` needs to be created, and
after that you use setters methods to modify the values.
``src/ZipStream.php`` file.
.. code-block:: php
use ZipStream\ZipStream;
use ZipStream\Option\Archive as ArchiveOptions;
require_once 'vendor/autoload.php';
$opt = new ArchiveOptions();
$zip = new ZipStream(
// Define output stream
// (argument is eiter a resource or implementing
// `Psr\Http\Message\StreamInterface`)
//
// Setup with `psr/http-message` & `guzzlehttp/psr7` dependencies
// required when using `Psr\Http\Message\StreamInterface`.
outputStream: $filePointer,
// Define output stream (argument is of type resource)
$opt->setOutputStream($fd);
// Set the deflate level (default is 6; use -1 to disable it)
defaultDeflateLevel: 6,
// Set the deflate level (default is 6; use -1 to disable it)
$opt->setDeflateLevel(6);
// Add a comment to the zip file
comment: 'This is a comment.',
// Add a comment to the zip file
$opt->setComment('This is a comment.');
// Send http headers (default is true)
sendHttpHeaders: false,
// Size, in bytes, of the largest file to try and load into memory (used by addFileFromPath()). Large files may also be compressed differently; see the 'largeFileMethod' option.
$opt->setLargeFileSize(30000000);
// HTTP Content-Disposition.
// Defaults to 'attachment', where FILENAME is the specified filename.
// Note that this does nothing if you are not sending HTTP headers.
contentDisposition: 'attachment',
// How to handle large files. Legal values are STORE (the default), or DEFLATE. Store sends the file raw and is significantly faster, while DEFLATE compresses the file and is much, much slower. Note that deflate must compress the file twice and is extremely slow.
$opt->setLargeFileMethod(ZipStream\Option\Method::STORE());
$opt->setLargeFileMethod(ZipStream\Option\Method::DEFLATE());
// Output Name for HTTP Content-Disposition
// Defaults to no name
outputName: "example.zip",
// Send http headers (default is false)
$opt->setSendHttpHeaders(false);
// HTTP Content-Type.
// Defaults to 'application/x-zip'.
// Note that this does nothing if you are not sending HTTP headers.
contentType: 'application/x-zip',
// HTTP Content-Disposition. Defaults to 'attachment', where FILENAME is the specified filename. Note that this does nothing if you are not sending HTTP headers.
$opt->setContentDisposition('attachment');
// Set the function called for setting headers.
// Default is the `header()` of PHP
httpHeaderCallback: header(...),
// Set the content type (does nothing if you are not sending HTTP headers)
$opt->setContentType('application/x-zip');
// Enable streaming files with single read where general purpose bit 3
// indicates local file header contain zero values in crc and size
// fields, these appear only after file contents in data descriptor
// block.
// Set to true if your input stream is remote
// (used with addFileFromStream()).
// Default is false.
defaultEnableZeroHeader: false,
// Set the function called for setting headers. Default is the `header()` of PHP
$opt->setHttpHeaderCallback('header');
// Enable zip64 extension, allowing very large archives
// (> 4Gb or file count > 64k)
// Default is true
enableZip64: true,
// Enable streaming files with single read where general purpose bit 3 indicates local file header contain zero values in crc and size fields, these appear only after file contents in data descriptor block. Default is false. Set to true if your input stream is remote (used with addFileFromStream()).
$opt->setZeroHeader(false);
// Enable reading file stat for determining file size. When a 32-bit system reads file size that is over 2 GB, invalid value appears in file size due to integer overflow. Should be disabled on 32-bit systems with method addFileFromPath if any file may exceed 2 GB. In this case file will be read in blocks and correct size will be determined from content. Default is true.
$opt->setStatFiles(true);
// Enable zip64 extension, allowing very large archives (> 4Gb or file count > 64k)
// default is true
$opt->setEnableZip64(true);
// Flush output buffer after every write
// default is false
$opt->setFlushOutput(true);
// Now that everything is set you can pass the options to the ZipStream instance
$zip = new ZipStream('example.zip', $opt);
// Flush output buffer after every write
// Default is false
flushOutput: true,
);

View File

@ -12,7 +12,10 @@ Example
---------------
.. code-block:: php
$stream = $response->getBody();
// add a file named 'streamfile.txt' from the content of the stream
$zip->addFileFromPsr7Stream('streamfile.txt', $stream);
$zip->addFileFromPsr7Stream(
fileName: 'streamfile.txt',
stream: $stream,
);

View File

@ -5,9 +5,9 @@ Stream to S3 Bucket
---------------
.. code-block:: php
use Aws\S3\S3Client;
use Aws\Credentials\CredentialProvider;
use ZipStream\Option\Archive;
use ZipStream\ZipStream;
$bucket = 'your bucket name';
@ -21,13 +21,19 @@ Stream to S3 Bucket
$zipFile = fopen("s3://$bucket/example.zip", 'w');
$options = new Archive();
$options->setEnableZip64(false);
$options->setOutputStream($zipFile);
$zip = new ZipStream(
enableZip64: false,
outputStream: $zipFile,
);
$zip = new ZipStream(null, $options);
$zip->addFile('file1.txt', 'File1 data');
$zip->addFile('file2.txt', 'File2 data');
$zip->addFile(
fileName: 'file1.txt',
data: 'File1 data',
);
$zip->addFile(
fileName: 'file2.txt',
data: 'File2 data',
);
$zip->finish();
fclose($zipFile);
fclose($zipFile);

View File

@ -31,7 +31,7 @@ stored in an AWS S3 bucket by key:
*/
public function zipStreamAction()
{
//sample test file on s3
// sample test file on s3
$s3keys = array(
"ziptestfolder/file1.txt"
);
@ -39,18 +39,18 @@ stored in an AWS S3 bucket by key:
$s3Client = $this->get('app.amazon.s3'); //s3client service
$s3Client->registerStreamWrapper(); //required
//using StreamedResponse to wrap ZipStream functionality for files on AWS s3.
// using StreamedResponse to wrap ZipStream functionality
// for files on AWS s3.
$response = new StreamedResponse(function() use($s3keys, $s3Client)
{
// Define suitable options for ZipStream Archive.
$options = new \ZipStream\Option\Archive();
$options->setContentType('application/octet-stream');
// this is needed to prevent issues with truncated zip files
$options->setZeroHeader(true);
$options->setComment('test zip file.');
//initialise zipstream with output zip filename and options.
$zip = new ZipStream\ZipStream('test.zip', $options);
$zip = new ZipStream\ZipStream(
outputName: 'test.zip',
defaultEnableZeroHeader: true,
contentType: 'application/octet-stream',
);
//loop keys - useful for multiple files
foreach ($s3keys as $key) {
@ -58,15 +58,19 @@ stored in an AWS S3 bucket by key:
//file using the same name.
$fileName = basename($key);
//concatenate s3path.
$bucket = 'bucketname'; //replace with your bucket name or get from parameters file.
// concatenate s3path.
// replace with your bucket name or get from parameters file.
$bucket = 'bucketname';
$s3path = "s3://" . $bucket . "/" . $key;
//addFileFromStream
if ($streamRead = fopen($s3path, 'r')) {
$zip->addFileFromStream($fileName, $streamRead);
$zip->addFileFromStream(
fileName: $fileName,
stream: $streamRead,
);
} else {
die('Could not open stream for reading');
die('Could not open stream for reading');
}
}
@ -123,4 +127,4 @@ You need to add correct permissions
's3' => ['ACL' => 'public-read'],
]);
fopen($path, 'w', null, $outputContext);
fopen($path, 'w', null, $outputContext);

View File

@ -22,11 +22,35 @@ Installation
Simply add a dependency on ``maennchen/zipstream-php`` to your project's
``composer.json`` file if you use Composer to manage the dependencies of your
project. Use following command to add the package to your project's dependencies:
project. Use following command to add the package to your project's
dependencies:
.. code-block:: sh
composer require maennchen/zipstream-php
If you want to use``addFileFromPsr7Stream```
(``Psr\Http\Message\StreamInterface``) or use a stream instead of a
``resource`` as ``outputStream``, the following dependencies must be installed
as well:
.. code-block:: sh
composer require psr/http-message guzzlehttp/psr7
If ``composer install`` yields the following error, your installation is missing
the `mbstring extension <https://www.php.net/manual/en/book.mbstring.php>`_,
either `install it <https://www.php.net/manual/en/mbstring.installation.php>`_
or run the follwoing command:
.. code-block::
Your requirements could not be resolved to an installable set of packages.
Problem 1
- Root composer.json requires PHP extension ext-mbstring * but it is
missing from your system. Install or enable PHP's mbstrings extension.
.. code-block:: sh
composer require symfony/polyfill-mbstring
Usage Intro
---------------
@ -37,25 +61,42 @@ Here's a simple example:
// Autoload the dependencies
require 'vendor/autoload.php';
// enable output of HTTP headers
$options = new ZipStream\Option\Archive();
$options->setSendHttpHeaders(true);
// create a new zipstream object
$zip = new ZipStream\ZipStream('example.zip', $options);
$zip = new ZipStream\ZipStream(
outputName: 'example.zip',
// enable output of HTTP headers
sendHttpHeaders: true,
);
// create a file named 'hello.txt'
$zip->addFile('hello.txt', 'This is the contents of hello.txt');
$zip->addFile(
fileName: 'hello.txt',
data: 'This is the contents of hello.txt',
);
// add a file named 'some_image.jpg' from a local file 'path/to/image.jpg'
$zip->addFileFromPath('some_image.jpg', 'path/to/image.jpg');
$zip->addFileFromPath(
fileName: 'some_image.jpg',
path: 'path/to/image.jpg',
);
// add a file named 'goodbye.txt' from an open stream resource
$fp = tmpfile();
fwrite($fp, 'The quick brown fox jumped over the lazy dog.');
rewind($fp);
$zip->addFileFromStream('goodbye.txt', $fp);
fclose($fp);
$filePointer = tmpfile();
fwrite($filePointer, 'The quick brown fox jumped over the lazy dog.');
rewind($filePointer);
$zip->addFileFromStream(
fileName: 'goodbye.txt',
stream: $filePointer,
);
fclose($filePointer);
// add a file named 'streamfile.txt' from the body of a `guzzle` response
// Setup with `psr/http-message` & `guzzlehttp/psr7` dependencies required.
$zip->addFileFromPsr7Stream(
fileName: 'streamfile.txt',
stream: $response->getBody(),
);
// finish the zip stream
$zip->finish();
@ -82,4 +123,4 @@ See `#146 <https://github.com/maennchen/ZipStream-PHP/issues/146>`_.
It is the responsability of the client code to make sure that files are not
saved with the same path, as it is not possible for the library to figure it out
while streaming a zip.
See `#154 <https://github.com/maennchen/ZipStream-PHP/issues/154>`_.
See `#154 <https://github.com/maennchen/ZipStream-PHP/issues/154>`_.