Создание и обслуживание сжатых файлов с помощью php - PullRequest
3 голосов
/ 17 сентября 2009

Я пытаюсь использовать следующий код для создания zip-файла из каталога и предоставления его пользователю через http-загрузку:

 // write the file
file_put_contents($path . "/index.html", $output);

// zip up the contents
chdir($path);
exec("zip -r {$course->name} ./");

$filename = "{$course->name}.zip";

header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=' .urlencode($filename));
header('Content-Transfer-Encoding: binary');

readfile($filename);

Я могу создать zip-файл, но загрузка его через http не работает. Если я загружаю zip-файл, созданный с использованием ftp-клиента, Mac Stuffit Expander прекрасно распаковывает файлы, но если я загружаю его по http, Mac unzipper создает бесконечный цикл. Под этим я подразумеваю, скажем, загружаемый файл, который называется course.zip, затем при разархивировании файла выдается файл course.zip.cpgz, а при распаковке этого файла снова появляется файл course.zip ..

У кого-нибудь есть идеи?

Спасибо!

Ответы [ 4 ]

8 голосов
/ 23 ноября 2009

У меня была эта проблема, и оказалось, что в загруженном zip-файле была вставлена ​​новая строка в самом начале.

Решено с помощью функций ob_clean и flush

    header("Pragma: public");
    header("Expires: 0");
    header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
    header("Cache-Control: private",false);
    header("Content-Type: application/octet-stream");
    header("Content-Disposition: attachment; filename=".basename($archive_file_name));
    header("Content-Transfer-Encoding: binary");
    header("Content-Length: ".filesize($archive_file_name));
    ob_clean();
    flush();
    echo readfile("$archive_file_name");
1 голос
/ 17 сентября 2009
  1. Повторная архивация при каждом запросе не очень хорошая идея. Попробуйте сделать это, только если ZIP-файл еще не существует.

  2. Если файл нестабильный или просто небольшой файл, который вы хотите передать сжатым, попробуйте использовать вместо него ob_start('ob_gzhandler'), проще, меньше, чище. Файл передается сжатым, но он сохраняется в исходном формате на стороне клиента.

  3. Указание заголовка Content-Length необходимо для того, чтобы загрузчик мог знать конец файла, позволяя контролировать прогресс, обнаруживать повреждение файла и избегать зависания сеанса HTTP (если Connection находится в Keep -Живом режиме), возможно, отсутствие этого заголовка является корнем проблемы.

1 голос
/ 17 сентября 2009

В соответствии с предложением karim79 я оставлю свой комментарий в качестве ответа: что произойдет, если вы измените тип MIME с application / octet-stream на application / zip?

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

0 голосов
/ 17 сентября 2009

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

Возможно, что браузер каким-то образом исказил zip-файл (кто-нибудь переводит новую строку?) В процессе загрузки. Как уже упоминалось, проверьте тип MIME и используйте заголовок php (), чтобы установить правильный тип MIME (application / zip).

...