GZip сжатие данных с использованием PHP

Многие броузеры поддерживают gzip сжатые файлы в "прозрачном" для пользователя режиме. Для html страниц коэфициент сжатия методом GZip составляет 0.2-0.3, т.е. данные сжимаются в 3-5 раз, что даёт такое же ускорение закачки страницы при прочих равных условиях.

Эфект от сжатия снижается, если вы используете много графики (gif, jpeg, png), flash (swf), других мультимедиа. Но если большинство данных у вас текстовые и HTML страница занимает более 50кб - смело используйте сжатие.

Как узнать, поддерживает ли браузер сжатие?
Браузер при запросе страницы передает информацию о поддержке gzip. Если переменная окружения http_accept_encoding содержит "gzip" или "x-gzip", значит поддерживает. Узнать об этом в php можно проверив переменную $http_server_vars['http_accept_encoding'] на вхождение "gzip";

Для того, чтобы использовать сжатие, PHP должен быть скомпилирован с библиотекой zlib. Её можна скачать здесь: http://www.gzip.org/zlib, но имеется она и в дистрибутиве php. При запуске "configure" нужно указать параметр -with-zlib или -with-zlib=/path/to/zlib. Пользователи windows должны прописать в php.ini "extension=php_zlib.dll" (php_zlib.dll должен быть в папке указанной в параметре "extension_dir=c:phpextensions")

Для сжатия страницы можно использовать два способа:

  • Весь вывод делать не через echo, а в отдельную переменную.
  • Весь вывод делать в буфер вывода, поставив в начале страницы ob_start().
ob_start(); //буферизация вывода
ob_implicit_flush(0); // выдача буфера только по команде ob_end_flush()

Когда вывод страницы окончен, мы получаем содержимое буфера через

$page = ob_get_contents();

сжимаем его функцией

$page = gzencode($page);

Перед выводом сжатой страницы нужно послать правильные заголовки

header('content-encoding: gzip');
header('vary: accept-encoding');
header('content-length: ' . strlen($page));

И вывести сжатую страницу

echo $page;

Конечно, можно все это делать ручками, а можно и использовать классы библиотеки pear "http_compress" и "cache_outputcompression". А ещё проще сохранить себе этот файл:

zip.php
function start()
{
    ob_start();
    ob_implicit_flush(0);
}

function output($compress = true, $use_etag = true, $send_body = true)
{
    $min_gz_size = 1024;
    $page = ob_get_contents();
    $length = strlen($page);
    ob_end_clean();

    if ($compress && extension_loaded('zlib') &&
        (strlen($page) > $min_gz_size) &&
        isset($globals['http_server_vars']['http_accept_encoding'])
    ) {
        $ae = explode(',', str_replace(' ', '', $globals['http_server_vars']['http_accept_encoding']));
        $enc = false;
        if (in_array('gzip', $ae)) {
            $enc = 'gzip';
        } else if (in_array('x-gzip', $ae))
            $enc = 'x-gzip';

        if ($enc) {
            $length = strlen($page);
            header('content-encoding: ' . $enc);
            header('vary: accept-encoding');
        } else {
            $compress = false;
        }
    } else
        $compress = false;

    if ($use_etag) {
        $etag = '"' . md5($page) . '"';
        header('etag: ' . $etag);
        if (isset($globals['http_server_vars']['http_if_none_match'])) {
            $inm = explode(',', $globals['http_server_vars']['http_if_none_match']);
            foreach ($inm as $i) {
                if (trim($i) == $etag) {
                    header('http/1.0 304 not modified');
                    $send_body = false;
                    break;
                }
            }
        }
    }

    if ($send_body) {
        header('content-length: ' . $length);
        echo $page;
    }
}

И включать его в нужные страницы:

include('zip.php');
start();
/*
cтраница
*/
output();

Источник: http://samouchka.net/2006/12/21/szhatie_dannykh_na_php.html


.