Большие возможности маленького сайта (Работа с Zip архивами)

Автор статьи: Феськов Кузьма
Сайт Автора: php.russofile.ru
E-mail Автора: kuzma@russofile.ru
Дата публикации: 26.04.2006

Не редок пример, когда мы с вами используем платный хостинг (за свои кровные) для реализации каких-то идей, которые вовсе не обязаны приносить прибыль. Само собой разумеется, для этих целей мы часто прибегаем к хорошему хостингу, но выбираем тариф минимально для нас подходящий, как правило, размер диска под сайт у нас ограничен определенным набором мегабайтов. Жизнь идет, сайт постепенно разрастается и дискового пространства начинает не хватать. И вот мы уже судорожно думаем, чтобы удалить и как бы все это оптимизировать, потому что выкладывать лишние баксы за дополнительное место нам очень не хочется.

В данном материале я поговорю об одном из вариантов оптимизации работы сайта. Многие мне возразят, что это, мол, не оптимизация, но, поскольку мы с вами говорим о небольшом сайте, а не о гиганте с тысячами человек в день, мои идеи вполне могут быть полезны. К тому же, этот материал вполне вам пригодится, если вы вдруг вздумаете использовать для каких-то других целей работу с архивами.

И так, начнем...

Не так давно я разрабатывал систему тестов, тесты хранились в отдельных XML файлах и каждый тест занимал незначительный объем – в пределах килобайта. Как вы понимаете, файлов было неисчислимое множество. Уже на этапе разработки мы насчитывали несколько тысяч тестов. Все это хоть и было структурировано, но лежало в каталогах по 1000 файлов в каждом. Работать с этим было тяжело, как вы понимаете, маленькие файлы занимают места часто больше, чем свой реальный размер...

И тут мне пришла в голову одна интересная идея. Те из вас, кто сталкивался с другими языками программирования, в частности, скажем, с Delphi, сталкивался и с таким понятием как файл ресурса – это единый файл, который содержит в себе иллюстрации, тексты, звуки и так далее. В результате чего программа из свалки файлов превращается в компактный набор из нескольких файлов. Файл ресурса вполне можно назвать архивом, поскольку файлы в нем хранятся в определенном формате.

Для разработки своей системы ресурсов я использовал архив формата ZIP и библиотеку PCLZip (http://www.phpconcept.net/pclzip/). Почему? Ну, во-первых, PHP очень хорошо умеет работать с такими архивами, а, во-вторых, алгоритм сжатия ZIP достаточно прост, чтобы загружать процессор в незначительной степени (в конечном итоге, мы вообще можем не сжимать файлы, а просто собирать их в один архив для удобства). Также, нам понадобится библиотека zlib (http://www.gzip.org/zlib/).

Давайте подготовим с вами архив ZIP, я, например, собрал в один архив те самые 1000 файлов из каталога, для эксперимента поставил самую высокую степень сжатия. Размер дискового пространства в значительной степени увеличился :-) А заодно у нас появился 1 файл вместо 1000.

Далее, скачиваем, указанную выше, библиотеку и копируем ее в нужный вам каталог.

Сначала давайте научимся находить в каком из архивов у нас нужный файл. Архивы у нас называются числами вида 0000.zip, 0001.zip, .... и так далее. Как я уже говорил, в каждом архиве у нас 1000 файлов. Вычисляем все очень просто. Берем ID теста из базы и ищем по нему номер архива:

$arch = substr(intval($ID / 1000) + 10000, 1, 4) . ‘.zip’;

В результате в переменной $arch у нас находится название нужного нам архива. Нужный нам файл в архиве будет называться $ID.xml.

Теперь нам остается достать нужный файл из архива:

// Подключаем библиотеку PCL Zip
require_once('pclzip.lib.php');

// Создаем объект $zip. В качестве параметра передаем имя архива.
$zip = new PclZip($arch);

// Извлекаем нужным нам файл в переменную
$content = $zip->extract(PCLZIP_OPT_BY_NAME, $ID . '.xml',
                         PCLZIP_OPT_EXTRACT_AS_STRING);

// Получаем содержимое файла
$content = $content[0]['content'];

Теперь переменная $content содержит текст нужного нам файла.

Я рекомендую вам ТОЛЬКО ИЗВЛЕКАТЬ данные из архива, но не добавлять их туда и не изменять архива. Поскольку эти действия значительно более затратные по сравнению с извлечением.

Таким же способом вы можете работать и с файлами контента вашего сайта. Поскольку объем страниц часто значительно превышает размер данных маленьких XML файлов, то имеет смысл распаковывать их на диск, а не в переменную и организовать кэширование. То есть хранить распакованное на диске в незапакованном виде, скажем, в течение получаса после распаковки. И если файл более не востребован, снова удалять его.

Далее, я опишу все функции библиотеки PCLZip.

PCLZip Руководство пользователя (v2.1)

PCLZip - это библиотека для создания и работы с архивами формата ZIP.

Библиотека определяет класс. Копия класса определяет только один архив. Методы, описываемые в этом руководстве, позволяют управлять заданным архивом.

Обратите внимание, публичные методы будут работать всегда (поддерживаться из версии в версию), модификации будут описаны в документации. Частные (внутренние) методы могут быть изменены без предупреждения и не должны использоваться при работе.

PCLZip находится в одном файле (pclzip.lib.php) – это все, что требуется, чтобы иметь весь арсенал библиотеки.

Понимание: как это работает?

Внутреннее представление архива.

Каждый архив PKZIP представлен объектом класса PCLZip. При создании объекта PCLZip (в объекте класса), имя архива ассоциируется с объектом. На данном этапе файл не читается и не проверяется, более того,он может даже не существовать.

  require_once('pclzip.lib.php');
  $archive = new PclZip("archive.zip");

Архив управляется публичными методами библиотеки PCLZip. Для создания архива, если он еще не существует, необходимо использовать метод 'create();' со списком файлов и/или папок как параметр.

Если архив уже существует, его содержание может читаться методами доступа, такими, как: 'listContent();' или 'extract();'.

Параметры и аргументы.

Каждый метод имеет свои параметры и аргументы, которые есть в описании метода. Эти аргументы могут быть принудительными или дополнительными. Пример:

  require_once('pclzip.lib.php');
  $archive = new PclZip('archive.zip');
  $v_list = $archive->add('dev/file.txt',
                          PCLZIP_OPT_REMOVE_PATH, 'dev');

Здесь первый параметр 'dev/file.txt' принудительный, а 'PCLZIP_OPT_REMOVE_PATH, ...' опциональный.

Некоторые методы можно вызывать только с переменным списком дополнительных параметров:

$list = $archive->extract(PCLZIP_OPT_PATH, "folder",
                          PCLZIP_OPT_REMOVE_PATH, "data",
                          PCLZIP_CB_PRE_EXTRACT, "callback_pre_extract",
                          PCLZIP_CB_POST_EXTRACT, "callback_post_extract");

В этом примере файлы распакованы в каталог 'folder', а папка 'data', имеющаяся в архиве, из архива удалена.

Также, перед извлечением файла из архива вызывалась возвратная функция, назначенная пользователем (здесь, 'callback_pre_extract();'). Эта функция позволяет изменить путь и имя файла, который находится в процессе извлечения или пропустить извлечение этого специфического файла. В конце извлечения вызывается другая функция, которая дает пользователю возможность проделать над файлом какие-то действия перед извлечением следующего.

      $list = $archive->extract(PCLZIP_OPT_PATH, "folder",
                                PCLZIP_OPT_REMOVE_ALL_PATH);

Здесь файлы извлечены в директорию 'folder', а все запомненные пути файлов удалены, даже если они были отличны. Эта особенность позволяет пользователю не определять точный путь для удаления.

Эти небольшие примеры показывают работу списка переменных. Они предлагают более точную работу (хотя и добавляют немного сложности). Они так же позволяют вводить новые возможности, не изменяя синтаксиса всех методов.

Все аргументы, их использование и ограничения описаны в разделе “Дополнительные переменные параметры”. В описании функций перечислен список всех доступных дополнительных параметров.

Возвращаемые данные.

Возвращаемые значения могут отличаться от метода к методу. Они описаны в каждом комментарии метода. Однако, большинство методов возвращают 0 при ошибке (и включают флаг ошибки) или массив, описывающий каждый файл при удаче.

Каждый элемент массива описывает файл или папку, некоторые из ее свойств и определение статуса последнего действия с файлом.

Каждый файл описан следующим набором аргументов:

filename

Имя файла

При добавлении – имя, данное файлу при вызове метода.

При извлечении – реальное название извлеченного файла (не название, которое дано этому файлу в архиве).

stored_filename

Название файла в архиве.

size

Реальный размер файла.

compressed_size

Размер сжатого файла (без заголовков).

mtime

Дата и время последней модификации файла (UNIX таймштамп).

сomment

Комментарий сопоставленный с файлом.

folder

true | false: показывает, находится ли файл в папке.

index

Индекс файла в архиве (если задано).

content

Содержимое извлеченного файла. Этот параметр присутствует только если в качестве аргумента было задано PCLZIP_OPT_EXTRACT_IN_STRING.

status

Результат действия (зависит от типа действия). Значения:

  • ok – положительный результат.
  • Filtered – файл/папка не извлечен (отфильтрован пользователем).
  • already_a_directory – файл не был извлечен, потому что файл или папка с таким же названием уже существует.
  • newer_exist – файл не был извлечен, потому что такой же файл уже существует и защищен от записи.
  • write_protect – файл не был извлечен, потому что существует более новый файл.
  • path_creation_fail – файл не был извлечен – произошла ошибка создания каталога.
  • write_error – файл не был извлечен – произошла ошибка записи.
  • read_error – файл не был извлечен – ошибка чтения.
  • invalid_header – файл не был извлечен – ошибка заголовка.
  • skipped – файл не был извлечен или добавлен, потому что пользовательская функция просит пропустить его.
  • filename_to_long – файл не добавлен в архив – слишком длинное имя файла (максимум 255 символов).

Дополнительные аргументы.

Краткий обзор.

Дополнительные аргументы могут быть разделены на две группы. Первые – классические аргументы, которые дают информацию или инструкции методу. - Вторые – функции возврата, крюки, которые дают пользователю возможность выполнить определенные действия в течении обработки PCLZip. “Функции возврата” сложны для понимания, но дают лучший контроль над архивированными файлами.

Дополнительные аргументы обозначены именем, которое является в сущности статическим целым значением. Значение аргумента может быть единственным или списком значений. В некоторых случаях они не имеют значения, а их название служит сигналом, чтобы выполнить какие-либо действия.

В следующем разделе мы опишем аргументы этих двух групп.

Дополнительные аргументы.

На сегодняшний день определены следующие аргументы:

PCLZIP_OPT_PATH

Этот аргумент указывает путь до папки, куда будут извлечены файлы из архива. Значение – текстовая строка.

      $list = $archive->extract(PCLZIP_OPT_PATH, "extract/folder/");

Этот аргумент может использоваться с методами 'extract();' и 'extractByIndex();'.

PCLZIP_OPT_ADD_PATH

Этот параметр позволяет указать путь для файла при добавлении его в архив. Это позволит заархивировать файл 'file.txt' с путем 'bacup/file.txt' или извлечь файл 'backup/file.txt' с путем 'folder/backup/file.txt'.

Значение – текстовая строка.

      $list = $archive->create("file.txt,image.gif",
                               PCLZIP_OPT_ADD_PATH, "backup");

Этот аргумент может использоваться с методами 'create();', 'add();', 'extract();'.

PCLZIP_OPT_REMOVE_PATH

Этот аргумент позволяет подавить часть или весь путь файлов (или папок) при их извлечении. Это позволит архивировать файл '/usr/local/user/test/file.txt' подобно файлу с названием 'test/file.txt' или извлекать файл, сохраненный как 'folder/data/file.txt' как файл 'data/file.txt'.

Значение – текстовая строка.

      $list = $archive->add("/usr/local/user/test/file.txt",
                            PCLZIP_OPT_REMOVE_PATH, "/usr/local/user");

Этот аргумент может использоваться совместно с методами 'create();', 'add();', 'extract();' и 'extractByIndex();'

Примечание: этот аргумент игнорируется, если вы используете аргумент PCLZIP_OPT_REMOVE_ALL_PATH в том же самом вызове метода.

PCLZIP_OPT_REMOVE_ALL_PATH

Этот аргумент позволяет подавить весь путь файла при его извлечении или добавлении в архив.

Этот параметр позволит вам не указывать ни какого шаблона пути для отсечения. Однако, будте внимательны, вложенность каталогов может быть большой, следите за тем, чтобы внутри не попадались файлы с одинаковым названием.

Значения не имеет.

  $list = $archive->create("data/file.txt images/image.gif",
                           PCLZIP_OPT_REMOVE_ALL_PATH);
  // Удалит путь 'data/' для файла 'data/file.txt'
  // и путь 'images/' для файла 'images/image.gif'

Может использоваться с методами 'create();', 'add();', 'extract();' и 'extractByIndex();'.

PCLZIP_OPT_SET_CHMOD

Дает возможность изменить атрибуты файла после его извлечения. На *NIX системах управление доступа и владелец файла (системный атрибут) не позволяют доступ к файлу отовсюду. В частности, пользователь, под которым запущен процесс PHP дает файлам только свои права, при определенных настройках они могут запрещать пользование файлами другими пользователями. Цель этого аргумента – назначить файлам нужные вам права.

Значение – одиночное октальное значение (например, 0777).

  $list = $archive->extract(PCLZIP_OPT_SET_CHMOD, 0777);

Этот аргумент может использоваться с методами 'extract();' и 'extractByIndex();'.

Примечание: этот аргумент не тестировался в полном объеме и носит статус ЭКСПЕРИМЕНТАЛЬНОГО.

PCLZIP_OPT_BY_NAME

Позволяет извлекать файлы из архива указывая их полное название.

    $archive = new PclZip('test.zip');
    $rule_list[0] = 'data/file1.txt';
    $rule_list[1] = 'data/file2.txt';
    $list = $archive->extract(PCLZIP_OPT_BY_NAME, $rule_list);
    if ($list == 0) {
      echo "ERROR : ".$archive->errorInfo(true);
    }

Фильтр может быть массивом или текстовой строкой с перечислением через запятую.

    $archive = new PclZip('test.zip');
    $list = $archive->extract(PCLZIP_OPT_BY_NAME, 
                              "data/file1.txt,data/file2.txt");
    if ($list == 0) {
      echo "ERROR : ".$archive->errorInfo(true);
    }

См. также: PCLZIP_OPT_BY_PREG, PCLZIP_OPT_BY_INDEX и PCLZIP_OPT_BY_EREG.

PCLZIP_OPT_BY_EREG

Этот параметр позволяет извлекать файлы и папки отфильтровывая их регулярным выражением. Используется функция PHP 'ereg()'.

    $archive = new PclZip('test.zip');
    $list = $archive->extract(PCLZIP_OPT_BY_EREG, "txt$");
    if ($list == 0) {
      echo "ERROR : ".$archive->errorInfo(true);
    }

См. также PCLZIP_OPT_BY_PREG, PCLZIP_OPT_BY_NAME и PCLZIP_OPT_BY_INDEX.

PCLZIP_OPT_BY_PREG

Этот параметр позволяет извлекать файлы и папки отфильтровывая их регулярным выражением. Используется функция PHP 'preg()'.

    $archive = new PclZip('test.zip');
    $list = $archive->extract(PCLZIP_OPT_BY_PREG, "txt$");
    if ($list == 0) {
      echo "ERROR : ".$archive->errorInfo(true);
    }

См. также PCLZIP_OPT_BY_EREG, PCLZIP_OPT_BY_NAME и PCLZIP_OPT_BY_INDEX.

PCLZIP_OPT_BY_INDEX

Позволяет извлекать файлы и папки указывая их индексы в архиве.

 $archive = new PclZip('test.zip');
 $list = $archive->extract(PCLZIP_OPT_BY_INDEX, array ('0-4','2-7','10-33'));
 if ($list == 0) {
   echo "ERROR : ".$archive->errorInfo(true);
 }

См. также PCLZIP_OPT_BY_PREG, PCLZIP_OPT_BY_NAME и PCLZIP_OPT_BY_EREG.

PCLZIP_OPT_EXTRACT_AS_STRING

Позволяет извлечь файл в строковую переменную а не в файл.

Это может понадобиться, если вы хотите получить содержимое файла без использования файловой системы.

Для примера:

  • показать 'readme' файл;
  • непосредственно выдать файл пользователю (смотри так же PCLZIP_OPT_EXTRACT_IN_OUTPUT).

Вы должны быть внимательными извлекая все файлы из архива. Это может привести к нехватке памяти.

    $archive = new PclZip('test.zip');
    $list = $archive->extract(PCLZIP_OPT_BY_NAME, "data/readme.txt",
                              PCLZIP_OPT_EXTRACT_AS_STRING);
    if ($list == 0) {
      echo "ERROR : ".$archive->errorInfo(true);
      exit;
    }
    echo $list[0]['content'];

См. также PCLZIP_OPT_EXTRACT_IN_OUTPUT.

PCLZIP_OPT_EXTRACT_IN_OUTPUT

Этот аргумент дает вам возможность извлечь файл непосредственно на устройство вывода, подобно команде echo.

    $archive = new PclZip('test.zip');
    $list = $archive->extract(PCLZIP_OPT_BY_NAME, "data/readme.txt",
                              PCLZIP_OPT_EXTRACT_IN_OUTPUT);
    if ($list == 0) {
      echo "ERROR : ".$archive->errorInfo(true);
    }

См. также PCLZIP_OPT_EXTRACT_AS_STRING.

PCLZIP_OPT_NO_COMPRESSION

Позволяет добавить файл в архив не сжимая его.

    $archive = new PclZip('test.zip');
    $list = $archive->add("data/file.txt", PCLZIP_OPT_NO_COMPRESSION);
    if ($list == 0) {
      echo "ERROR : ".$archive->errorInfo(true);
    }


PCLZIP_OPT_COMMENT

Позволяет добавить комментарий к архиву. Если комментарий уже существует, заменит его.

    $archive = new PclZip('test.zip');
    $list = $archive->create("data", PCLZIP_OPT_COMMENT, "Add a comment");
    if ($list == 0) {
      echo "ERROR : ".$archive->errorInfo(true);
    }

См. также PCLZIP_OPT_ADD_COMMENT и PCLZIP_OPT_PREPEND_COMMENT.

PCLZIP_OPT_ADD_COMMENT

Позволяет добавить комментарий к архиву. Если комментарий уже существует, добавит новый комментарий в конец существующего.

    $archive = new PclZip('test.zip');
    $list = $archive->add("data", PCLZIP_OPT_ADD_COMMENT, 
                          "Add a comment after the existing one");
    if ($list == 0) {
      echo "ERROR : ".$archive->errorInfo(true);
    }

См. также PCLZIP_OPT_COMMENT и PCLZIP_OPT_PREPEND_COMMENT.

PCLZIP_OPT_PREPEND_COMMENT

Позволяет добавить комментарий к архиву. Если комментарий уже существует, добавит новый комментарий перед имеющимся.

    $archive = new PclZip('test.zip');
    $list = $archive->add("data", PCLZIP_OPT_PREPEND_COMMENT, 
                          "Add a comment before the existing one");
    if ($list == 0) {
      echo "ERROR : ".$archive->errorInfo(true);
    }

См. также PCLZIP_OPT_COMMENT и PCLZIP_OPT_ADD_COMMENT.

Возвратные функции.

Возвратные функции – специфические аргументы, потому что их значение – название функции. Эти функции имеют строгое описание и которого вы должны придерживаться. Действия, которые могут производить эти функции разграничены. Внутренний алгоритм функции может быть любым, но он должен уважать определенный список параметров и возвращаемых значений. Однако, функция должна уважать основную обработку метода, некоторое действия могут с этим столкнуться (например, удаление файла архива в течении процесса).

PCLZIP_CB_PRE_EXTRACT

Этот дополнительный аргумент дает вам возможность выполнить определенную функцию перед тем как распаковать файл. Эта функция может изменять процесс извлечения файла двумя способами:

  • изменить путь или имя файла;
  • пропустить извлечение файла.

Чтобы быть точными: эта функция применяется после дополнительных аргументов PCLZIP_OPT_PATH, PCLZIP_OPT_ADD_PATH, PCLZIP_OPT_REMOVE_PATH или PCLZIP_OPT_REMOVE_ALL_PATH, но перед конкретной проверкой (файл не существует, файла нет в текущей папке, и так далее).

Функция должна принимать в качестве аргументов следующие параметры:

    function myCallBack($p_event, &$p_header)
    {
    [... ваш код ...]
    return $result;
    }

Когда метод вызывает возвратную функцию, он делает это следующим образом:

  • $p_event – идентификатор аргумента (здесь PCLZIP_CB_PRE_EXTRACT). Это используется, когда необходимо использовать одну и ту же функцию для разных возвратных действий.
  • $p_header – описание файла, который будте извлечен. Это массив, который содержит информацию в нескольких полях. Наиболее интересный параметр – имя файла в архиве и имя файла, под которым он будет извлечен. Все поля массива описаны в главе “Возвращаемые данные”.

Функция может менять только поле “filename” (имя файла) в массиве $p_header. Это дает вам вам возможность изменить имя файла после распаковки. Все остальные параметры массива только для чтения.

Функция должна возвратить 2, 1 или 0 ($result). Другие значения зарезервированы на будущее. 1 – означает возобновление извлечения файла (возможно, с измененным именем файла). 0 – пропустить файл, переходим к следующему файлу. 2 – пропустить файл и остановить распаковку, даже если не достигнут конец архива.

  function myPreExtractCallBack($p_event, &$p_header)
  {
    $info = pathinfo($p_header['filename']);
    // ----- пропускаем все .gif файлы
    if ($info['extension'] == 'gif') {
      return 0;
    }
    // ----- jpg файлы распаковываем в папку 'images'
    else if ($info['extension'] == 'jpg') {
      $p_header['filename'] = 'images/'.$info['basename'];
      return 1;
    }
    // ----- остальные файлы просто распаковываем
    else {
      return 1;
    }
  }

  $list = $archive->extract(PCLZIP_OPT_PATH, 'folder',);
                            PCLZIP_CB_PRE_EXTRACT, 'myPreExtractCallBack');



PCLZIP_CB_POST_EXTRACT

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

Функция должна принимать в качестве аргументов следующие параметры:

    function myCallBack($p_event, &$p_header)
    {
    [... ваш код ...]
    return $result;
    }
  • $p_event – идентификатор аргумента (здесь PCLZIP_CB_POST_EXTRACT). Это используется, когда необходимо использовать одну и ту же функцию для разных возвратных действий.
  • $p_header – описание файла, который будте извлечен. Это массив, который содержит информацию в нескольких полях. Наиболее интересный параметр – имя файла в архиве и имя файла, под которым он будет извлечен. Все поля массива описаны в главе “Возвращаемые данные”. Функция не может менять этот массив, потому что извлечение уже произошло.

Функция должна возвратить 1 или 2 ($result). Остальные значения зарезервированы на будущее. 1 – извлекаем дальше. 2 – останавливаем извлечение.

  function myPreExtractCallBack($p_event, &$p_header) { ... }

  function myPostExtractCallBack($p_event, &$p_header)
  {
    // ----- проверяем успешность распаковки
    if ($p_header['status'] == 'ok') {
      // ----- читаем файл
      readfile($p_header['filename']);
      // ----- удаляем файл
      unlink($p_header['filename'])
    }
  }

  $list = $archive->extract(PCLZIP_OPT_PATH, 'temp',
                            PCLZIP_CB_PRE_EXTRACT, 'myPreExtractCallBack',
                            PCLZIP_CB_POST_EXTRACT, 'myPostExtractCallBack');

Таким образом, эта функция производит действия над распакованным файлом, а затем удаляет его.

Примечание, в данном конкретном примере логичнее использовать параметр PCLZIP_OPT_EXTRACT_IN_OUTPUT, так как он не создает промежуточного файла.

PCLZIP_CB_PRE_ADD

Этот параметр позволяет вам добавить обработку файла перед помещением его в архив. Вы можете, например:

  • изменить путь или имя файла;
  • пропустить извлечение файла.

Чтобы быть точными: эта функция применяется после дополнительных аргументов PCLZIP_OPT_PATH, PCLZIP_OPT_ADD_PATH, PCLZIP_OPT_REMOVE_PATH или PCLZIP_OPT_REMOVE_ALL_PATH, но перед конкретной проверкой (файл не существует, файла нет в текущей папке, и так далее).

Функция должна принимать в качестве аргументов следующие параметры:

    function myCallBack($p_event, &$p_header)
    {
    [... ваш код ...]
    return $result;
    }

Когда метод вызывает возвратную функцию, он делает это следующим образом:

  • $p_event – идентификатор аргумента (здесь PCLZIP_CB_PRE_ADD). Это используется, когда необходимо использовать одну и ту же функцию для разных возвратных действий.
  • $p_header – описание файла, который будте извлечен. Это массив, который содержит информацию в нескольких полях. Наиболее интересный параметр – имя файла в архиве и имя файла, под которым он будет добавлен. Все поля массива описаны в главе “Возвращаемые данные”.

Функция может менять только поле “filename” (имя файла) в массиве $p_header. Это дает вам вам возможность изменить имя файла перед запаковкой. Все остальные параметры массива только для чтения.

Функция должна возвратить 1 или 0 ($result). Другие значения зарезервированы на будущее. 1 – означает возобновление добавления файла (возможно, с измененным именем файла). 0 – пропустить файл, переходим к следующему файлу.

  function myPreAddCallBack($p_event, &$p_header)
  {
    $info = pathinfo($p_header['stored_filename']);
    // ----- пропускаем .bak файлы
    if ($info['extension'] == 'bak') {
      return 0;
    }
    // ----- jpg файлы будут добавляться в папку 'images'
    else if ($info['extension'] == 'jpg') {
      $p_header['stored_filename'] = 'images/'.$info['basename'];
      return 1;
    }
    // ----- остальные файлы просто добавляются
    else {
      return 1;
    }
  }

  $list = $archive->add(PCLZIP_CB_PRE_ADD, 'myPreAddCallBack');


PCLZIP_CB_POST_ADD

Этот параметр позволяет запустить нужную функцию после добавления файла. Эта функция не может повлиять на добавление файла, но может произвести действия с файлом на диске, например переименовать или удалить.

Функция должна принимать в качестве аргументов следующие параметры:

    function myCallBack($p_event, &$p_header)
    {
    [... ваш код ...]
    return $result;
    }

  • $p_event – идентификатор аргумента (здесь PCLZIP_CB_POST_ADD). Это используется, когда необходимо использовать одну и ту же функцию для разных возвратных действий.
  • $p_header – описание файла, который будте извлечен. Это массив, который содержит информацию в нескольких полях. Наиболее интересный параметр – имя файла на диске и имя файла, под которым он будет добавлен. Все поля массива описаны в главе “Возвращаемые данные”. Функция не может менять этот массив, потому что добавление уже произошло.

Функция должна возвратить 1. Остальные значения зарезервированы на будущее.

  function myPostAddCallBack($p_event, &$p_header)
  {
    // ----- проверяем удачное добавление
    if ($p_header['status'] == 'ok') {
      // ----- перемещаем файлы в корзину
      rename($p_header['filename'], 'trash/'.$p_header['filename'])
    }
  }

  $list = $archive->extract(PCLZIP_CB_POST_ADD, 'myPostAddCallBack');

Обработка ошибок.

С версии 1.3 обработка ошибок встроена в класс для того чтобы получился единый файл. Однако вы и сейчас можете вынести обработку ошибок во внешний модуль. Читайте раздел “Настройка PCLZip”.

Когда метод возвращает код ошибки (большинство методов возвращает 0 при ошибке), код ошибки, текст ошибки и дополнительная информация доступна через методы:

  • errorName(); - возвращает строку с названием ошибки;
  • errorCode(); - возвращает значение кода ошибки;
  • errorInfo(); - возвращает описание, связанное с ошибкой.

Примеры обработки ошибок:

Читаем код ошибки:

  $list = $archive->extract(PCLZIP_OPT_PATH, "extract/folder/");
  if ($list == 0) {
    die ("Unrecoverable error, code ".$archive->errorCode());
  }

Неустранимая ошибка, код -6.

Читаем название ошибки:

  $list = $archive->extract(PCLZIP_OPT_PATH, "extract/folder/");
  if ($list == 0) {
    die ("Unrecoverable error '".$archive->errorName()."'");
  }

Неустранимая ошибка 'PCLZIP_ERR_BAD_FORMAT'.

Читаем название ошибки и ее код:

  $list = $archive->extract(PCLZIP_OPT_PATH, "extract/folder/");
  if ($list == 0) {
    die ("Unrecoverable error '".$archive->errorName(true)."'");
  }

Неустранимая ошибка 'PCLZIP_ERR_BAD_FORMAT (-10)'.

Чтение описания ошибки:

  $list = $archive->extract(PCLZIP_OPT_PATH, "extract/folder/");
  if ($list == 0) {
    die ("Error : '".$archive->errorInfo()."'");
  }

Ошибка: Неправильная структура архива [код -10].

Чтение полного описания:

  $list = $archive->extract(PCLZIP_OPT_PATH, "extract/folder/");
  if ($list == 0) {
    die ("Error  : '".$archive->errorInfo(true)."'");
  }

Ошибка: 'PCLZIP_ERR_BAD_FORMAT (-10): Неправильная структура архива'.

Класс. методы.

PclZip()

Обзор.

Этот метод – конструктор объекта.

Резюме.

PclZip($zipname);

Аргументы.

$zipname – строка – название файла формата ZIP.

Описание.

Этот метод создает объект PclZip, который работает с архивом формата ZIP. Устанавливается только имя архива, никакой проверки не производится, никаких действий не выполняется.

При создании объекта производится проверка установки zlib. Если не установлено – сообщение об ошибке.

Пример:

  require_once('pclzip.lib.php');
  $archive = new PclZip('archive.zip');
  if ($archive->create('file.txt data/text.txt folder/') == 0) {
    die('Error : '.$archive->errorInfo(true));
  }


create()

Обзор.

Этот метод создает архив формата ZIP с указанными файлами.

Резюме.

create($filelist, [доп. Параметры])

Аргументы.

$filelist

Массив с названиями файлов или директорий

или

строка с названием файла или директории

или

строка с названиями файлов или директорий, разделенными запятыми.

Дополнительные аргументы:

  • PCLZIP_OPT_REMOVE_PATH
  • PCLZIP_OPT_REMOVE_ALL_PATH
  • PCLZIP_OPT_ADD_PATH
  • PCLZIP_CB_PRE_ADD
  • PCLZIP_CB_POST_ADD
  • PCLZIP_OPT_NO_COMPRESSION
  • PCLZIP_OPT_COMMENT


Возвращаемые значения:

0 – ошибка.

Массив – параметры файлов (См. “Возвращаемые значения”).

Описание.

Этот метод создает архив со всеми файлами и папками, обозначенными в аргументе $filelist. После добавления всех файлов и папок структура filesystem будет запомнена.

Дополнительные аргументы аргументы дают возможность архивировать файлы с различными путями. Это позволяет помещать архивируемые файлы в другое место, а в архиве создавать необходимую структуру.

Примеры:

  include_once('pclzip.lib.php');
  $archive = new PclZip('archive.zip');
  $v_list = $archive->create('file.txt,data/text.txt,folder');
  if ($v_list == 0) {
     die("Error : ".$archive->errorInfo(true));
  }

В этом примере мы создали архив 'archive.zip' и поместили в него файлы 'file.txt' и 'data/text.txt'. Все из папки 'folder' также было добавлено включая все вложенные поддиректории.

     include_once('pclzip.lib.php');
     $archive = new PclZip('archive.zip');
     $v_list = $archive->create('data/file.txt,data/text.txt',
                                PCLZIP_OPT_REMOVE_PATH, 'data',
                                PCLZIP_OPT_ADD_PATH, 'install');
     if ($v_list == 0) {
        die("Error : ".$archive->errorInfo(true));
     }

В этом примере файлы 'file.txt' и 'text.txt', которые находятся в локальной папке 'data' , добавлены в архив без папки 'data', но в папку 'install'. Они сохранены в архиве как 'install/file.txt' и 'install/text.txt'.

listContent()

Обзор.

Этот метод возвращает список свойств файлов и папок.

Резюме.

listContent()

Возвращаемые значения.

0 – ошибка.

Массив – формат массива смотрите в разделе “Возвращаемые значения”.

Описание.

Этот метод возвращает содержание архива. Результат – массив, каждый элемент которого описывает архивированный файл или папку.

Пример:

     include_once('pclzip.lib.php');

     $zip = new PclZip("test.zip");

     if (($list = $zip->listContent()) == 0) {
        die("Error : ".$zip->errorInfo(true));
     }

     for ($i=0; $i<sizeof($list); $i++) {
        for(reset($list[$i]); $key = key($list[$i]); next($list[$i])) {
            echo "File $i / [$key] = ".$list[$i][$key]."<br>";
        }
        echo "<br>";
     }

Пример выведет следующий результат:

File 0 / [filename] = data/file1.txt
File 0 / [stored_filename] = data/file1.txt
File 0 / [size] = 53
File 0 / [compressed_size] = 36
File 0 / [mtime] = 1010440428
File 0 / [comment] =
File 0 / [folder] = 0
File 0 / [index] = 0
File 0 / [status] = ok

File 1 / [filename] = data/file2.txt
File 1 / [stored_filename] = data/file2.txt
File 1 / [size] = 54
File 1 / [compressed_size] = 53
File 1 / [mtime] = 1011197724
File 1 / [comment] =
File 1 / [folder] = 0
File 1 / [index] = 1
File 1 / [status] = ok


extract()

Обзор.

Этот метод распаковывает файлы и папки из архива формата ZIP.

Резюме.

PclZip::extract([список параметров])

Аргументы.

  • PCLZIP_OPT_PATH
  • PCLZIP_OPT_REMOVE_PATH
  • PCLZIP_OPT_REMOVE_ALL_PATH
  • PCLZIP_OPT_ADD_PATH
  • PCLZIP_CB_PRE_EXTRACT
  • PCLZIP_CB_POST_EXTRACT
  • PCLZIP_OPT_SET_CHMOD
  • PCLZIP_OPT_BY_NAME
  • PCLZIP_OPT_BY_EREG
  • PCLZIP_OPT_BY_PREG
  • PCLZIP_OPT_BY_INDEX
  • PCLZIP_OPT_EXTRACT_AS_STRING
  • PCLZIP_OPT_EXTRACT_IN_OUTPUT


Возвращаемые значения.

0 – ошибка.

Массив – массив с извлеченными файлами. Обратите внимание, если извлечение какого-либо файла терпит неудачу, то это не значит, что все извлечение потерпело неудачу. Но статус файла в массиве будет указывать на причину ошибки. (См. “Возвращаемые параметры”).

Описание.

Этот метод извлекает часть или все файлы из архива формата ZIP.

Фильтрация может быть задана дополнительными аргументами. Также вы можете изменить путь для извлечения файлов и папок. При извлечении маленьких файлов вы можете не создавать промежуточных файлов извлекая их прямо в переменную. Также вы можете отдавать распаковываемый файл напрямую пользователю (См. “Дополнительные аргументы”).

Примеры:

     require_once('pclzip.lib.php');
     $archive = new PclZip('archive.zip');
     if ($archive->extract() == 0) {
        die("Error : ".$archive->errorInfo(true));
     }

В этом примере все файлы будут извлечены в текущую директорию.

     include('pclzip.lib.php');
     $archive = new PclZip('archive.zip');
     if ($archive->extract(PCLZIP_OPT_PATH, 'data',
                           PCLZIP_OPT_REMOVE_PATH, 'install/release') == 0) {
        die("Error : ".$archive->errorInfo(true));
     }

В этом примере все файл извлечены в папку 'data'. Все файлы с префиксом 'install/release' также распакованы в папку 'data', а не в 'data/install/release'.

properties()

Обзор.

Этот метод отдает общие свойства архива в формате ZIP.

Резюме.

PclZip::properties()

Возвращаемые значения.

0 – ошибка.

Массив – массив со свойствами архива.

Описание.

Этот метод возвращает общие свойства архива формата ZIP.

Доступные свойства:

  • nb – число папок/файлов в архиве.
  • comment – комментарий, связанный с архивом.
  • status – статус архива (сейчас доступен только ОК).


add()

Обзор.

Этот метод добавляет файлы или папки в архиву формата ZIP.

Резюме.

PclZip::add($filelist, [доп. параметры])

Аргументы.

$filelist

Массив с названиями файлов или директорий

или

строка с названием файла или директории

или

строка с названиями файлов или директорий, разделенными запятыми.

Дополнительные параметры.

  • PCLZIP_OPT_REMOVE_PATH
  • PCLZIP_OPT_REMOVE_ALL_PATH
  • PCLZIP_OPT_ADD_PATH
  • PCLZIP_CB_PRE_ADD
  • PCLZIP_CB_POST_ADD
  • PCLZIP_OPT_NO_COMPRESSION
  • PCLZIP_OPT_COMMENT
  • PCLZIP_OPT_ADD_COMMENT
  • PCLZIP_OPT_PREPEND_COMMENT


Возвращаемые значения.

0 – ошибка.

Массив – см. “Возвращаемые значения”.

Описание.

Этот метод позволяет добавлять в уже существующий архив файлы, перечисленные в $filelist. После добавления всех файлов и папок структура filesystem запоминается.

Будте осторожны, если такой файл в архиве уже существует, то он добавится в конец архива, но не заменит существующий.

Если архив не существует, он будет автоматически создан.

Описание дополнительных аргументов смотрите в соответствующей главе.

Примеры:

     require_once('pclzip.lib.php');
     $archive = new PclZip('archive.zip');
     $v_list = $archive->add('file.txt,data/text.txt,folder/');
     if ($v_list == 0) {
       die("Error : ".$archive->errorInfo(true));
     }

В этом примере в архив добавляются файл 'file.txt', 'date/text.txt' и все содержимое папки 'folder'.

     require_once('pclzip.lib.php');
     $archive = new PclZip('archive.zip');
     $v_list = $archive->add('dev/file.txt,dev/text.txt',
                             PCLZIP_OPT_ADD_PATH, 'install',
                             PCLZIP_OPT_REMOVE_PATH, 'dev');
     if ($v_list == 0) {
       die("Error : ".$archive->errorInfo(true));
     }

В этом примере файлы 'dev/file.txt' и 'dev/text.txt' добавляются в архив, однако, путь 'dev' удалена и заменена на 'install'. Поэтому файлы в архиве сохранены как 'install/file.txt' и 'install/text.txt'.

delete()

Обзор.

Этот метод позволяет удалить из архива все или часть файлов.

Резюме.

PclZip::delete([список параметров])

Аргументы.

  • PCLZIP_OPT_BY_NAME
  • PCLZIP_OPT_BY_EREG
  • PCLZIP_OPT_BY_PREG
  • PCLZIP_OPT_BY_INDEX


Возвращаемые значения.

0 – ошибка.

Массив – Список файлов и их свойства (оставшихся в архиве). Формат массива см. “Возвращаемые параметры”.

Описание.

Этот метод удаляет все или часть файлов, находящихся в архиве.

Вы можете использовать аргументы для организации фильтра.

Примеры:

     require_once('pclzip.lib.php');
     $archive = new PclZip('archive.zip');
     $v_list = $archive->delete();
     if ($v_list == 0) {
         die("Error : ".$archive->errorInfo(true));
     }

В этом примере из архива будут удален все файлы.

     require_once('pclzip.lib.php');
     $archive = new PclZip('archive.zip');
     $v_list = $archive->delete(PCLZIP_OPT_BY_INDEX, '1-3,5,8-10');
     if ($v_list == 0) {
        die("Error : ".$archive->errorInfo(true));
     }

В этом образце будут удалены файлы в индексе 1-3, 5 и 8-10. Файлы и папки могут быть получены методом listContent().

Примечание, папка имеет свой собственный вход (с ее собственным индексом). При удалении папки, файлы, принадлежащие ей, удалены не будут.

     require_once('pclzip.lib.php');
     $archive = new PclZip('archive.zip');
     $v_list = $archive->delete(PCLZIP_OPT_BY_EREG, 'txt$');
     if ($v_list == 0) {
        die("Error : ".$archive->errorInfo(true));
     }

В этом примере будут удалены все файлы, заканчивающиеся на .txt.

merge()

Обзор.

Склеивает два архива. Добавляет новый архив в конец имеющегося.

Резюме.

PclZip::merge($archive_filename)

Аргументы.

$archive_filename

Имя файла архива, с которым будет происходить объединение.

Возвращаемые значения.

0 – ошибка.

1 – удача.

Описание.

Функция добавляет содержимое архива с именем $archive_filename к текущем архиву. Никакой проверки делаться не будет, например, дубликаты файлов обнаружены не будут. Это не функция обновления! Эта функция “глупо” склеивает два архива.

duplicate()

Обзор.

Дублирует архив.

Резюме.

PclZip::duplicate($archive_filename)

Аргументы.

$acrhive_filename

Имя архива для дублирования.

Возвращаемые значения.

0 – ошибка.

1 – удача.

Описание.

Эта функция создает копию архива с именем из $archive_filename. Объект PclZip должен быть только создан. К нему не должны применяться никакие действия. Если связать его с уже существующим архивом, то этот архив будет удален и заменен дублируемым архивом.


На этом все – удачной работы!