«PHP-Creative»

 

Меню сайта


Новые статьи



Статистика

Rambler's Top100

Рейтинг@Mail.ru

Сейчас на сайте: 1

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

Дата добавления: 2009-04-18

Автор статьи: Феськов Кузьма

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

Не так давно я разрабатывал систему тестов, тесты хранились в отдельных 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();'.

Просмотров: 6950

Комментарии к данной статье:

К данной статье нет комментариев.

Добавить новый комментарий:

Введите сумму чисел с картинки:

Реклама