Создание и обслуживание архивированных файлов с помощью php

StackOverflow https://stackoverflow.com/questions/1436239

  •  07-07-2019
  •  | 
  •  

Вопрос

Я пытаюсь использовать следующий код для создания 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-клиента, то программа Stuffit Expander Mac отлично разархивирует файлы, но если я загружаю его по http, программа mac unzipper создает бесконечный цикл.Под этим я подразумеваю, что файл, который я загружаю, называется course.zip, затем при распаковке файла выдается файл course.zip.cpgz, а при распаковке этого файла снова появляется course.zip .. и так далее, и тому подобное.

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

Спасибо!

Это было полезно?

Решение

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

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

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

Другие советы

У меня была эта проблема, и оказалось, что загруженный 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");

Как было предложено карим79, Я помещу свой комментарий в качестве ответа:что произойдет, если вы измените тип MIME с application / octet-stream на application / zip?

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top