My original code does this:
$data = file_get_contents($source);
$compressed_data = gzencode($data);
file_put_contents($destination, $compressed_data);
This works fine, and it seemingly supports a lot of different values for $source
and $destination
- including in-memory file systems, stdin/stdout streams, etc.
However, large files have to be fully loaded into memory, so I'd like to switch this over to a chunked approach.
I've tried the following:
$in = fopen($source, 'rb');
$out = gzopen($destination, 'wb');
while (!feof($in)) {
gzwrite($out, fread($in, 4096));
}
But this gives me an error with stream wrappers (such as https://packagist.org/packages/mikey179/vfsstream): gzopen(): cannot represent a stream of type user-space as a File Descriptor
.
Also tried the following:
$in = fopen($source, 'rb');
$out = fopen($destination, 'wb');
stream_filter_append($out, 'zlib.deflate', STREAM_FILTER_WRITE, -1);
while (!feof($in)) {
fwrite($out, fread($in, 4096));
}
But the resulting output doesn't appear to be valid GZIP (missing header maybe?)
Finally I tried this:
$in = fopen($source, 'rb');
$out = fopen('compress.zlib://' . $destination, 'wb');
while (!feof($in)) {
fwrite($out, fread($in, 4096));
}
But (unsurprisingly) this failed if $destination
already had a wrapper (such as php://stdin
or the vfs://
mentioned above).
There has to be a way to do this, but searching hasn't turned up any examples for it.
My Answer:
One way to achieve writing a chunked gzip file to an arbitrary output stream in PHP is to use the `Zlib` extension. Here's an example code snippet that demonstrates how to do this:
php
$source = 'path/to/source/file';
$destination = 'path/to/destination/file';
$in = fopen($source, 'rb');
$out = fopen($destination, 'wb');
stream_filter_append($out, 'zlib.deflate', STREAM_FILTER_WRITE, ['window' => 15]);
while (!feof($in)) {
$chunk = fread($in, 4096);
fwrite($out, $chunk);
}
fclose($in);
fclose($out);
In this code snippet:
- We open the source file in read mode and the destination file in write mode.
- We append the `zlib.deflate` filter to the output stream, which will compress the data using gzip compression.
- We read the source file in chunks of 4096 bytes and write each chunk to the output stream.
- Finally, we close both input and output streams.
This approach should work for writing chunked gzip files to various types of output streams, including file streams, memory streams, and others.
Rate this post
5 of 5 based on 6514 votesComments