gzdeflate() и большой объем данных

Я создаю класс для создания ZIP-файлов в PHP. Альтернатива ZipArchive, предполагающая, что это не разрешено на сервере. Что-то, что можно использовать с этими бесплатными серверами.

Это уже работает, создайте структуры ZIP с помощью PHP и используйте gzdeflate() для создания сжатых данных.

Проблема в том, что gzdeflate() требует от меня загрузки всего файла в память, и я хочу, чтобы класс работал с ограничением в 32 МБ памяти. В настоящее время он хранит файлы размером более 16 МБ без сжатия.

Я предполагаю, что мне нужно заставить его сжимать данные в блоках, 16 МБ на 16 МБ, но я не знаю, как объединить результат двух gzdeflate().

Я тестировал его, и кажется, что он требует некоторой математики в последних 16 битах, вроде buff->last16bits = (buff->last16bits & newblock->first16bits) | 0xfffe, это работает, но не для всех образцов...

Вопрос: как соединить два DEFLATE-потока, не распаковывая их?


person Havenard    schedule 09.09.2009    source источник


Ответы (2)


Потоковые фильтры PHP используются для выполнения таких задач. stream_filter_append можно использовать при чтении или записи в потоки. . Например

    $fp = fopen($path, 'r');
    stream_filter_append($fp, 'zlib.deflate', STREAM_FILTER_READ);

Теперь fread вернет вам дефлированные данные.

person Naveed    schedule 09.11.2012
comment
LOL 3 года, чтобы получить ответ! Я даже не проверял это, но это действительно очень хороший трюк, спасибо, сэр! - person Havenard; 09.03.2013

Это может помочь или не помочь. Похоже, что gzwrite позволит вам записывать файлы, не загружая их полностью в память. Этот пример со страницы руководства по PHP показывает, как вы можете сжать файл, используя gzwrite и fopen.

http://us.php.net/manual/en/function.gzwrite.php

function gzcompressfile($source,$level=false){
    // $dest=$source.'.gz';
    $dest='php://stdout'; // This will stream the compressed data directly to the screen.
    $mode='wb'.$level;
    $error=false;
    if($fp_out=gzopen($dest,$mode)){
        if($fp_in=fopen($source,'rb')){
            while(!feof($fp_in))
                gzwrite($fp_out,fread($fp_in,1024*512));
            fclose($fp_in);
            }
          else $error=true;
        gzclose($fp_out);
        }
      else $error=true;
    if($error) return false;
      else return $dest;
}
person Dooltaz    schedule 09.09.2009
comment
Может быть, я мог бы использовать это и получить сжатые данные из файла результатов, но это был бы большой беспорядок... должен же быть какой-то способ... - person Havenard; 09.09.2009
comment
Вы пытаетесь передать сжатые данные? - person Dooltaz; 09.09.2009
comment
Я просто изменил код. Теперь он будет выводить прямо на экран, чтобы вы могли передавать большие файлы. - person Dooltaz; 09.09.2009
comment
Нет, я пытаюсь создать ZIP-файлы. - person Havenard; 09.09.2009
comment
В zlib defate() для этого есть флаг Z_NO_FLUSH, но PHP gzdeflate() этого не делает... - person Havenard; 09.09.2009