Как создать потоковый zip-архив на PHP, подходящий для утилиты архивирования OS X? - PullRequest
2 голосов
/ 30 ноября 2011

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

Для этого я использую сторонний класс PHP, называемый ZipStream. Класс размещен здесь , а конкретный файл класса можно посмотреть здесь . Я выбрал эту версию (есть другая, более старая ), поскольку она поддерживает включение каталогов. Также, установка должна работать на серверах без доступа к командам оболочки через shell_exec() или passthru().

Моя простая настройка теста работает, и я могу извлечь полученный поточный zip с помощью команды unzip из консоли или с помощью The Unarchiver.app. Утилита архивирования OS X (Mac OS X 10.6 и, скорее всего, более ранние и более поздние версии) вызывает проблемы, поскольку не удается извлечь архив со следующей ошибкой:

Unable to unarchive "test.zip" into "test". (Error 1 - Operation not permitted.)

Фактическая зарегистрированная ошибка:

ditto: Couldn't read pkzip signature.

Я нашел несколько возможных объяснений относительно этой проблемы, здесь и здесь, в StackOverflow , и я хотел бы исправить класс ZipStream, чтобы он соответствовал спецификации Zip, чтобы утилита архивирования расширит архив как положено.

«Версия, необходимая для извлечения» (хранящаяся в константе ATTR_VERSION_TO_EXTRACT) в классе ZipStream: x0Ax00, но я не уверен, отличается ли эта запись от стандарта 0x000A, упомянутого в вышеупомянутый вопрос.

Кажется, проблема связана с каталогами, добавленными в zip-файл. Файл zip, содержащий только текстовый файл, не вызывает проблем при использовании утилиты архивирования.

Поскольку это движется вдоль границ области PHP, я не уверен, как отредактировать сценарий с правильными шестнадцатеричными строками или как присвоить решение Zend этому конкретному сценарию.

Я загрузил сгенерированный почтовый индекс здесь: http://dl.dropbox.com/u/6887873/test.zip

Генерируемый код является урезанной версией примера кода:

$extime = ini_get('max_execution_time');
ini_set('max_execution_time', 600);

include_once("ZipStream.php");

$fileTime = date("D, d M Y H:i:s T");

$chapter1 = "Chapter 1\n"
. "Lorem ipsum\n"
. "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec magna lorem, mattis sit amet porta vitae, consectetur ut eros. Nullam id mattis lacus. In eget neque magna, congue imperdiet nulla. Aenean erat lacus, imperdiet a adipiscing non, dignissim eget felis. Nulla facilisi. Vivamus sit amet lorem eget mauris dictum pharetra. In mauris nulla, placerat a accumsan ac, mollis sit amet ligula. Donec eget facilisis dui. Cras elit quam, imperdiet at malesuada vitae, luctus id orci. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Pellentesque eu libero in leo ultrices tristique. Etiam quis ornare massa. Donec in velit leo. Sed eu ante tortor.\n";

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

$zip->addFile("Hello World!\r\n", "Hello.txt");

$zip->addDirectory("files/");
$zip->addDirectoryContent("../images", "files/testing/");

$zip->finalize();

EDIT:

Я думаю, что я немного сузил проблему. Не похоже, что шестнадцатеричные строки действительно имеют значение. Сгенерированный zip-файл, содержащий только текстовый файл, расширяется без ошибок с помощью Archive Utility, поэтому кажется, что происходит повреждение при добавлении каталогов, особенно при вызове addDirectoryContent(), который, в свою очередь, вызывает addLargeFile() класса ZipStream. Каталоги добавляются правильно и не приводят к неверному файлу, как только в смесь добавляется addDirectoryContent(), утилите архивирования не удается извлечь файлы, что приводит к вышеприведенным ошибкам.

...