gzdeflate () и большой объем данных - PullRequest
3 голосов
/ 09 сентября 2009

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

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

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

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

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

Вопрос: Как объединить два потока DEFLATEd без его распаковки?

Ответы [ 2 ]

1 голос
/ 09 ноября 2012

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

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

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

0 голосов
/ 09 сентября 2009

Это может или не может помочь. Похоже, gzwrite позволит вам записывать файлы, не загружая их полностью в память. Этот пример со страницы PHP Manual показывает, как вы можете сжать файл, используя 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;
}
...