PHP файлы ZIP на лету
Какой самый простой способ сделать zip, скажем 2 файла, из папки на сервере и принудительно загрузить? Не сохраняя "zip" на сервере.
$zip = new ZipArchive();
//the string "file1" is the name we're assigning the file in the archive
$zip->addFile(file_get_contents($filepath1), 'file1'); //file 1 that you want compressed
$zip->addFile(file_get_contents($filepath2), 'file2'); //file 2 that you want compressed
$zip->addFile(file_get_contents($filepath3), 'file3'); //file 3 that you want compressed
echo $zip->file(); //this sends the compressed archive to the output buffer instead of writing it to a file.
Может ли кто-нибудь проверить:
У меня есть папка с test1.doc, test2.doc и test3.doc
с приведенным выше примером - file1 (file2 и file3) может быть просто test1.doc и т.д.
Мне нужно что-либо делать с "$ filepath1"? Это папка, в которой хранятся 3 документа?
Извините за мой основной вопрос..
Ответы
Ответ 1
К сожалению, с PHP 5.3.4-dev и Zend Engine v2.3.0 на CentOS 5.x я не смог получить вышеприведенный код. Сообщение об ошибке "Неверный или унифицированный объект Zip" было всем, что я мог получить. Поэтому, чтобы заставить его работать, мне пришлось использовать следующий фрагмент (взятый из примера Джонатаном Балтазаром в руководстве PHP.net на странице ZipArchive:: open):
// Prepare File
$file = tempnam("tmp", "zip");
$zip = new ZipArchive();
$zip->open($file, ZipArchive::OVERWRITE);
// Stuff with content
$zip->addFromString('file_name_within_archive.ext', $your_string_data);
$zip->addFile('file_on_server.ext', 'second_file_name_within_archive.ext');
// Close and send to users
$zip->close();
header('Content-Type: application/zip');
header('Content-Length: ' . filesize($file));
header('Content-Disposition: attachment; filename="file.zip"');
readfile($file);
unlink($file);
Я знаю, что это отличается от работы с памятью - если только у вас нет области tmp в ram;-) - но, возможно, это может помочь кому-то другому, кто борется с решением выше, как и я; и для которых штраф за исполнение не является проблемой.
Ответ 2
Ваш код очень близок. Вам нужно использовать имя файла вместо содержимого файла.
$zip->addFile(file_get_contents($filepath1), 'file1');
должен быть
$zip->addFile($filepath1, 'file1');
http://us3.php.net/manual/en/function.ziparchive-addfile.php
Если вам нужно добавить файлы из переменной вместо файла, вы можете использовать функцию addFromString.
$zip->addFromString( 'file1', $data );
Ответ 3
Если у вас есть доступ к утилите командной строки zip, вы можете попробовать
<?php
$zipped_data = `zip -q - files`;
header('Content-type: application/zip');
header('Content-Disposition: attachment; filename="download.zip"');
echo $zipped_data;
?>
где файлы - это то, что вы хотите заархивировать и закрепить в zip файле.
Это предполагает Linux или подобное, конечно. Думаю, что в Windows вы могли бы сделать подобное с другим инструментом сжатия.
Также существует расширение zip, использование показано здесь.
Ответ 4
maraspin Ответ - это то, что я пробовал. Как ни странно, я получил его, удалив строку заголовка, которая ссылается на размер файла:
header('Content-Length: ' . filesize($file));
С приведенным выше изменением код работает как ветер!
Без этого изменения я получил следующее сообщение об ошибке:
Подпись под конец центральной директории не найдена. Либо этот файл не является zipfile, либо представляет собой один диск из многочастного архива. В последнем случае центральный каталог и комментарий zipfile будут найдены на последнем диске (иях) этого архива.
Условия тестирования:
ОС: Ubuntu 10.10
Браузер: Firefox
И стек LAMP по умолчанию.
Ответ 5
itsols
Если вы хотите вставить "Content-Length", сделайте следующее:
$length = filesize($file);
header('Content-Length: ' . $length);
Я не знаю почему, но он падает, если вы поместите его в одну строку.
Ответ 6
Чтобы создавать ZIP файлы на лету (в памяти), вы можете использовать класс ZipFile
из phpMyAdmin:
Пример того, как использовать его в своем приложении:
Примечание.. Ваши ZIP файлы будут ограничены пределом памяти PHP, что приведет к повреждению архива, если вы превысите лимит.