PHP ZIP файлы на лету - PullRequest
45 голосов
/ 30 июня 2009

Какой самый простой способ заархивировать, скажем, 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 документами?

Извините за мой основной вопрос ..

Ответы [ 6 ]

69 голосов
/ 06 декабря 2010

К сожалению, с PHP 5.3.4-dev и Zend Engine v2.3.0 на CentOS 5.x Я не смог заставить работать приведенный выше код. Сообщение об ошибке « Invalid или unitialized Zip object » - все, что я мог получить. Итак, чтобы заставить его работать, мне пришлось использовать следующий фрагмент (взятый из примера Джонатана Балтазара в руководстве по 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 ;-) - но, возможно, это может помочь кому-то еще, кто борется с решением выше, как я; и для которого снижение производительности не является проблемой.

9 голосов
/ 30 июня 2009

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

$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 );
5 голосов
/ 30 июня 2009

Если у вас есть доступ к утилите командной строки 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 голосов
/ 28 апреля 2011

maraspin's ответ - это то, что я пытался. Странно, я получил это, удалив строку заголовка, которая ссылается на размер файла:

header('Content-Length: ' . filesize($file));

С вышеуказанным изменением код работает как бриз! Без этого изменения я получал следующее сообщение об ошибке:

Подпись конца центрального каталога не найдена. Либо этот файл не является zip-файлом, либо он представляет собой один диск из многочастного архива. В последнем случае центральный каталог и комментарий к zipfile будут найдены на последнем диске (ах) этого архива.

Тестовая среда:

ОС: Ubuntu 10.10 Браузер: Firefox И стек LAMP по умолчанию.

1 голос
/ 26 июня 2015

Для создания файлов ZIP на лету (в памяти) вы можете использовать ZipFile класс из phpMyAdmin :

Пример использования его в вашем приложении:

Примечание: Размер ваших ZIP-файлов будет ограничен пределом памяти PHP, что приведет к повреждению архива, если вы превысите предел.

1 голос
/ 11 августа 2011

itsols Если вы хотите вставить «Content-Length», сделайте это так:

$length = filesize($file);
header('Content-Length: ' . $length);

Не знаю почему, но он вылетает, если поставить его в одну строку.

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