PHP 8.4.1 Released!

Фільтри для стиснення

Оскільки обгортки для стиснення надають спосіб створення gzip— і bz2—сумісних файлів в локальній файловій системі, вони не надають засоби для загального стиснення мережевих потоків або переведення не стисненого потоку в стиснений. Натомість фільтр для стиснення може застосовуватися до будь-якого ресурсу потоку в будь-який час.

Зауваження: Фільтри для стиснення не генерують заголовки чи закінчення, використовуючи утиліти командного рядка, такі як gzip. Вони лише стискають і розтискають потрібні порції даних потоку.

zlib.deflate та zlib.inflate

zlib.deflate (стиснення) та zlib.inflate (розтиснення) є реалізаціями методів для стиснення, описаних у » RFC 1951. Фільтр deflate приймає до трьох параметрів, що передаються як асоціативний масив. level вказує силу стиснення числом від 1 до 9. Вищі числа, як правило, означатимуть стиснення даних до менший розміру, що коштуватиме додаткового процесорного часу. Також існують два спеціальні рівні стиснення: 0 (взагалі без стиснення) і -1 (звичайний внутрішній для zlib — зараз 6). window це двійковий логарифм розміру вікна петлі стиснення. Вищі значення (до 15 — 32768 байтів) дають краще стиснення, використовуючи більше пам'яті, коли нижчі значення (менше 9 — 512 байтів) — гірше стиснення при меншому обсязі пам'яті. Початково параметр window дорівнює 15. memory є шкалою, що визначає, скільки пам'яті для роботи повинно бути виділено. Діапазон допустимих значень від 1 (мінімальна кількість пам'яті) до 9 (максимум). Це виділення пам'яті впливає лише на швидкість, а не на розмір згенерованих даних.

Зауваження: Оскільки рівень стиснення є найбільш використовуваним параметром, він натомість може задаватися, як просте числове значення (замість елемента масиву).

Фільтри стиснення zlib.* є доступними, якщо увімкнена підтримка zlib.

Приклад #1 zlib.deflate та zlib.inflate

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

$original_text = "Це тест.\nЦе тільки тест.\nЦе неважливий рядок.\n";
echo
"Початковий текст містить " . strlen($original_text) . " символ(ів).\n";

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

echo
"Стиснений файл має " . filesize('test.deflated') . " байт(ів).\n";
echo
"Початковий текст був:\n";
/* Для розтиснення на льоту використовується функція readfile та фільтр zlib.inflate */
readfile('php://filter/zlib.inflate/resource=test.deflated');

/* Генерує вивід:

Початковий текст містить 81 символ(ів).
Стиснений файл має 72 байт(ів).
Початковий текст був:
Це тест.
Це тільки тест.
Це неважливий рядок.

*/
?>

Приклад #2 Простий zlib.deflate

<?php
$original_text
= "Це тест.\nЦе тільки тест.\nЦе неважливий рядок.\n";
echo
"Початковий текст має " . strlen($original_text) . " символ(ів).\n";

$fp = fopen('test.deflated', 'w');
/* "6" — вказує рівень стиснення */
stream_filter_append($fp, 'zlib.deflate', STREAM_FILTER_WRITE, 6);
fwrite($fp, $original_text);
fclose($fp);

echo
"Стиснений файл має " . filesize('test.deflated') . " байт(ів).\n";

/* Генерує вивід:

Початковий текст має 81 символ(ів).
Стиснений файл має 66 байт(ів).

*/
?>

bzip2.compress та bzip2.decompress

bzip2.compress та bzip2.decompress виконують роботу, схожу зі zlib-фільтрами, як описано вище. Фільтр bzip2.compress приймає до двох параметрів у вигляді асоціативного масиву: blocks — це ціле число від 1 до 9 визначає кількість блоків пам'яті розміром у 100кБ, яку потрібно виділити для роботи. work — це також ціле число в діапазоні від 0 до 250, яке вказує, скільки зусиль потрібно витратити, використовуючи звичайний метод стиснення, перш ніж повернутися до повільнішого, але надійнішого методу. Використання цього параметру впливає лише на швидкість стиснення. Цей параметр не змінює ані розмір стисненого виводу, ані використання пам’яті. Коефіцієнт роботи 0 вказує використовувати внутрішнє стандартне значення бібліотеки bzip. Фільтр bzip2.decompress приймає лиш один параметр, якому задається звичайне логічне значенням або елемент small асоціативного масиву. Коли small має значення true, бібліотека bzip виконує розстиснення, використовуючи найменше пам'яті, проте повільно.

Фільтри стиснення bzip2.* доступні, якщо увімкнена підтримка bz2.

Приклад #3 bzip2.compress та bzip2.decompress

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

echo
"Початковий файл має " . filesize('LICENSE') . " байт(ів).\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
"Стиснений файл має " . filesize('LICENSE.compressed') . " байт(ів).\n";

/* Генерує вивід:

Початковий файл має 3288 байт(ів).
Стиснений файл 1488 байт(ів).

*/
?>
add a note

User Contributed Notes 4 notes

up
9
Anonymous
9 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
6 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