Если я сделаю url для zip–файла href
ссылки и нажмите ссылку, мой zip-файл будет загружен и откроется, он получит содержимое, как я ожидаю.
Вот что такое HTML:
<a href="http://mysite.com/uploads/my-archive.zip">download zip</a>
Проблема в том, что я хотел бы, чтобы ссылка указывала на мое приложение, чтобы я мог определить, имеет ли пользователь право доступа к этому zip-файлу.
поэтому я бы хотел, чтобы мой HTML был следующим:
<a href="/canDownload">download zip</a>
и мой PHP для страницы /canDownload
:
//business logic to determine if user can download if($yesCanDownload){ $archive='https://mysite.com/uploads/my-archive.zip'; header("Content-Type: application/zip"); header("Content-Disposition: attachment; filename=".basename($archive)); header("Content-Length: ".filesize($archive)); ob_clean(); flush(); echo readfile("$archive"); }
Итак, я думаю, что проблема связана с кодом header()
но я пробовал кучу вещей, связанных с этим, основанным на различных рекомендациях Google и других SO, и никто не работает.
Если вы ответите на мой вопрос, вполне вероятно, что вы тоже можете ответить на этот вопрос: Zipped-файл с PHP приводит к созданию файла cpgz после извлечения
Ответ в моем случае состоял в том, что перед readfile () выводилась пустая строка.
Поэтому я добавил:
ob_end_clean ();
ReadFile ($ файла);
Но вы, вероятно, должны искать место, где эта строка выводится в вашем коде.
Документация PHP для readfile говорит, что она выведет содержимое файла и вернет int.
Итак, ваш код, echo readfile("$archive");
, будет echo $archive
(btw, двойные кавычки здесь бессмысленны, вы должны их удалить), а THEN выводит возвращаемый int
. То есть ваша строка должна быть: readfile($archive);
Кроме того, вы должны использовать локальный путь (а не ссылку http: //) в архив.
Итого:
if($yesCanDownload){ $archive='/path/to/my-archive.zip'; header("Content-Type: application/zip"); header("Content-Disposition: attachment; filename=".basename($archive)); header("Content-Length: ".filesize($archive)); ob_clean(); flush(); readfile($archive); }
Наконец, если это не сработает, убедитесь, что filesize($archive)
возвращает точную длину файла.
Еще один возможный ответ, который я нашел. После долгих поисков я обнаружил, что двумя возможными причинами *.zip
«распаковки» в *.zip.cpgz
являются:
*.zip
файл поврежден Будучи пользователем Mac, вторая причина была причиной моей проблемы с распаковкой файла: стандартным средством Mac OS является утилита архива , и, по-видимому, она не может обрабатывать> 2GB-файлы. (Этот файл для меня был зашифрованным диском на диске размером 4 ГБ .)
В результате я решил использовать виртуальную машину Debian, уже существующую в Virtual Box на моем Mac. unzip
6.0 на Debian 8.2 без проблем unzip
архив.
Вы передаете URL-адрес readfile()
следующим образом:
$archive = 'https://mysite.com/uploads/my-archive.zip';
Хотя вы должны передать путь на сервере, например:
$archive = '/uploads/my-archive.zip';
Предполагая, что файл находится в папке загрузки.
Кроме того, попробуйте следующие заголовки:
header("Content-type: application/octet-stream"); header("Content-disposition: attachment; filename=file.zip");
Хорошо, я ответил на свой вопрос.
Основная проблема, о которой я изначально не прояснил, заключалась в том, что файл не был размещен на моем сервере приложений. Это было в ковше Amazon AWS s3. Вот почему я использовал полный URL-адрес в моем вопросе, http://mysite...
и не просто путь к файлу на сервере. Как выясняется, fopen()
может открывать URL-адреса (все объекты «buck» s3 », aka-файлы, имеют URL-адреса), так что это то, что я сделал.
Вот мой последний код:
$zip= "http://mysite.com/uploads/my-archive.zip"; // my Amazon AWS s3 url header("Content-Type: archive/zip"); // works with "application/zip" too header("Content-Disposition: attachment; filename='my-archive.zip"); // what you want to call the downloaded zip file, can be different from what is in the s3 bucket $zip = fopen($zip,"r"); // open the zip file echo fpassthru($zip); // deliver the zip file exit(); //non-essential