CakeFest 2024: The Official CakePHP Conference

Filtres de compression

Alors que les enveloppes de compression fournissent un moyen pour générer des fichiers aux formats gzip et bz2, ils ne permettent pas de gérer les protocoles réseaux compressés, ni de commencer avec un flux non compressé pour le transformer en flux compressé. Pour cela, un filtre de compression peut être appliqué à tout moment sur n'importe quelle ressource de flux.

Note: Les filtres de compression ne génèrent pas les en-têtes et fins de fichiers, comme le fait l'utilitaire gzip. Ils ne font que compresser et décompresser des portions de flux de données.

zlib.deflate and zlib.inflate

zlib.deflate (compression) et zlib.inflate (décompression) sont les implémentations des méthodes de compression présentées dans la » RFC 1951. Le filtre deflate prend jusqu'à trois paramètres, passés sous la forme de tableau associatif. level spécifie le niveau de compression souhaité, de 1 à 9. Plus le niveau est haut, meilleure est la compression, et plus cher est le coût de compression. Deux niveaux de compression spéciaux existent : 0, qui représente l'absence de compression, et -1, qui représente le niveau par défaut de zlib : actuellement, 6. window est la taille du tampon mémoire, en base 2. Les valeurs supérieures, jusqu'à 15, soit 32768 octets, donnent de meilleures compressions, et les valeurs inférieures, jusqu'à 9, soit 512 octets, occupent le moins d'espace en mémoire. Par défaut, window vaut actuellement 15. memory est une indication du niveau de mémoire nécessaire. Les valeurs valides vont de 1, pour l'allocation minimale, à 9, pour une allocation maximale. L'allocation de mémoire affecte la vitesse d'exécution, et non pas le coût global.

Note: Comme le niveau de compression est le paramètre le plus courant, il peut aussi être fourni en tant que valeur entier, au lieu d'un tableau.

Les filtres de compression zlib.* sont disponibles si le support de zlib est activé.

Exemple #1 zlib.deflate and zlib.inflate

<?php
$params
= array('level' => 6, 'window' => 15, 'memory' => 9);

$original_text = "This is a test.\nThis is only a test.\nThis is not an important string.\n";
echo
"Le texte original est long de " . strlen($original_text) . " octets.\n";

$fp = fopen('test.deflated', 'w');
stream_filter_append($fp, 'zlib.deflate', STREAM_FILTER_WRITE, $params);
fwrite($fp, $original_text);
fclose($fp);

echo
"Le fichier compressé fait " . filesize('test.deflated') . " octets de long.\n";
echo
"Le texte original était :\n";
/* Utilise readfile et zlib.inflate pour décompresser à la volée */
readfile('php://filter/zlib.inflate/resource=test.deflated');

/* Affiche :

Le texte original est long de 70 octets
Le fichier compressé fait 56 octets de long.
Le texte original était :
This is a test.
This is only a test.
This is not an important string.

*/
?>

Exemple #2 zlib.deflate simple

<?php
$original_text
= "This is a test.\nThis is only a test.\nThis is not an important string.\n";
echo
"Le texte original est long de " . strlen($original_text) . " octets.\n";

$fp = fopen('test.deflated', 'w');
/* Ici, "6" indique le niveau de compression de 6 */
stream_filter_append($fp, 'zlib.deflate', STREAM_FILTER_WRITE, 6);
fwrite($fp, $original_text);
fclose($fp);

echo
"Le fichier compressé fait " . filesize('test.deflated') . " octets de long.\n";

/* Affiche :

Le texte original est long de 70 octets
Le fichier compressé fait 56 octets de long.

*/
?>

bzip2.compress and bzip2.decompress

bzip2.compress et bzip2.decompress fonctionnent de la même manière que les filtres zlib décrits ci-dessus. Le filtre bzip2.compress accepte jusqu'à 2 paramètres, sous la forme d'un tableau associatif : blocks est une valeur entier, de 1 à 9, spécifiant le nombre de blocs de 100 kb de mémoire à allouer à l'espace de travail. work est aussi un entier dont la valeur va de 0 à 250, et qui indique le niveau d'effort fourni avec une méthode de compression avant de passer à une autre méthode, plus lente. Modifier ce paramètre n'a qu'un effet sur la vitesse de compression. Le gain d'espace ou la mémoire utilisée restent les mêmes. Un niveau de 0 indique que la bibliothèque doit utiliser sa configuration par défaut. Le filtre bzip2.decompress accepte uniquement un paramètre, qui peut être passé sous la forme d'un booléen, ou en tant que l'élément small d'un tableau associatif. small, lorsque défini à true, indique à la bibliothèque bzip qu'elle doit faire une décompression en utilisant le moins de mémoire possible, aux dépends de la vitesse.

Les filtres bzip2.* sont disponibles si le support de bz2 est activé.

Exemple #3 bzip2.compress et bzip2.decompress

<?php
$param
= array('blocks' => 9, 'work' => 0);

echo
"Le fichier original fait " . strlen(LICENSE) . " octets de long.\n";

$fp = fopen('LICENSE.compressed', 'w');
stream_filter_append($fp, 'bzip2.compress', STREAM_FILTER_WRITE, $param);
fwrite($fp, file_get_contents('LICENSE'));
fclose($fp);

echo
"Le fichier compressé fait " . filesize('LICENSE.compressed') . " octets de long.\n";

/* Affiche :

Le fichier original fait 3288 octets de long.
Le fichier compressé fait 1488 octets de long.

*/
?>
add a note

User Contributed Notes 4 notes

up
9
Anonymous
8 years ago
To read a gzip encoded stream from http
<?php
$opts
= [
"http" => [
"method" => "GET",
"header" => [ "Accept-Encoding: gzip" ],
]
];
$ctx = stream_context_create($opts);
$f = fopen("http://php.net", "r", false, $ctx);
// check stream_get_meta_data($f)["wrapper_data"] has "Content-Encoding: gzip"
stream_filter_append($f, "zlib.inflate", STREAM_FILTER_READ, ["window" => 30]);
echo
stream_get_contents($f); // any stream processing
fclose($f);
up
1
Anonymous
3 years ago
To use the zlib.inflate filter with data originally written using gzcompress() or zlib.deflate, set the window option to 15 as outlined here: https://bugs.php.net/bug.php?id=68556

<?php
$fh
= fopen(file_name, 'rb');
stream_filter_append($fh, 'zlib.inflate', STREAM_FILTER_READ, ['window' => 15]);
$contents = stream_get_contents($fh);
fclose($fh);
up
2
bohwaz
5 years ago
Please note that there is currently a bug in this feature. ftell(), fseek() and fstat() functions cannot be used. Writing to a stream after using this function will not change the stream position as it should.

See bug: https://bugs.php.net/bug.php?id=49874

Also the zlib filters don't work with php://temp, php://memory and php://input streams, nothing is outputted to those streams.
up
-1
TingSong
1 year ago
To decompress a gzipped stream:

<?php
$stream
= fopen('https://example.com/some/file.txt.gz', 'rb');
stream_filter_append($stream, 'zlib.inflate', STREAM_FILTER_READ, ['window' => 15+16]);

// read the decompressed line directly
$line = fgets($stream);

// process the lines
?>

As the doc of zlib https://www.zlib.net/manual.html#Advanced

The 'window' parameter between 8 and 15 specified the window size from 2⁸ to 2¹⁵ bytes. It can be added by 16 for wrapping with gzip header and trailer instead of zlib wrapper.

And, window could be -8..-15 for unwrapping RAW deflate data.
To Top