PHP: Compressing and Uncompressing Files

Wednesday, March 11, 2009

Compressing data is usually a good thing, especially when file space and network bandwidth are always at premium. PHP provides a set of functions that allow you to deal with compressed files and make them yourself. Note that these functions are immediately available under Windows and some other binary distributions, although you may need to specifically compile PHP with Zlib support to access these functions on other machines.

Before we go further, it should also be noted that there is rarely a need to bother to compress the output of your PHP script to send it to the browser. The reason is that PHP has this capability automatically built in, and you can enable it for all your pages if you want by changing the value of the zlib.output_compression setting in your php.ini file. To read more about this, see http://php.net/zlib.

One good use of this is to store various data files that you may want to access in compressed format to save space but to read them into memory when needed. Here's a demo:

<?php
$data = gzfile('compressed-data.gz');
?>


Another common use is to store raw files that will be served to the public in gzipped format but use PHP to serve them back up in the end. The following shows a script that takes a filename passed in and returns the contents of said file uncompressed. Use it, for example, by calling it in an image source tag like this:
<img src="decompress.php?file=image.jpg" alt="A Photo" width="100" height="150" />


Uncompress Files for Serving
<?php
$file = $_GET['file'];
if (($file{0} == '/') || (strstr($file, '..') !== false)) {
    exit("ERROR: Attempt to navigate directory tree detected!");
}

$parts = pathinfo($file);
switch (strtolower($parts['extension'])) {
    case 'gif':
        header('Content-type: image/gif');
        break;
    case 'jpg':
    case 'jpeg':
        header('Content-type: image/jpeg');
        break;
    case 'png':
        header('Content-type: image/png');
        break;
    case 'html':
        header('Content-type: text/html');
        break;
    default:
        exit("ERROR: Unsupported filetype accessed!");
}
readgzfile("{$file}.gz");
?>


Finally you may want to take data that is passed into your script and compress it for storage into a file. This way you can allow for uploaded files on a system but mitigate the amount of disk space used by this feature. Using gzencode() prepares data to be written to a gzip file as shown here. (Also of note are gzdeflate() and gzinflate(), which can be used to compress and restore data for storage in a binary field of a database.)

Compressing User Input
<?php
$ized = serialize($_REQUEST);
$compressed = gzencode($ized, 9);
$filename = tempnam('.', 'GZ-');
file_put_contents($filename, $compressed);
?>


Hope it helps.

0 comments: