Манипулировать архивом в памяти с помощью PHP (без создания временного файла на диске)
Я пытаюсь создать архив на лету в PHP и немедленно отправить его пользователю (не сохраняя его). Я решил, что нет необходимости создавать файл на диске, поскольку данные, которые я отправляю, в любом случае не постоянны, однако при поиске в Интернете я не мог понять, как это сделать. Мне также не нужен формат файла.
Итак, вопрос:
Возможно ли создать и обработать файловый архив в памяти в php script без создания временного файла на этом пути?
Ответы
Ответ 1
У меня была такая же проблема, но, наконец, я нашел несколько неясное решение и решил поделиться им здесь.
Я столкнулся с большими сценариями zip.lib.php
/unzip.lib.php
, которые поставляются с phpmyadmin
и находятся в каталоге "libraries".
Использование zip.lib.php
работало как прелесть для меня:
require_once(LIBS_DIR . 'zip.lib.php');
...
//create the zip
$zip = new zipfile();
//add files to the zip, passing file contents, not actual files
$zip->addFile($file_content, $file_name);
...
//prepare the proper content type
header("Content-type: application/octet-stream");
header("Content-Disposition: attachment; filename=my_archive.zip");
header("Content-Description: Files of an applicant");
//get the zip content and send it back to the browser
echo $zip->file();
Этот script позволяет загружать zip, не требуя наличия файлов в качестве реальных файлов или сохранения самого zip в качестве файла.
Позор, что эта функция не является частью более общей библиотеки PHP.
Вот ссылка на файл zip.lib.php
из источника phpmyadmin:
https://github.com/phpmyadmin/phpmyadmin/blob/RELEASE_4_5_5_1/libraries/zip.lib.php
UPDATE:
Убедитесь, что вы удалили следующую проверку с начала zip.lib.php, так как иначе script просто завершается:
if (! defined('PHPMYADMIN')) {
exit;
}
UPDATE:
Этот код также доступен в проекте CodeIgniter:
https://github.com/patricksavalle/CodeIgniter/blob/439ac3a87a448ae6c2cbae0890c9f672efcae32d/system/helpers/zip_helper.php
Ответ 2
что вы используете для создания архива? Возможно, вы сможете использовать память потока php://temp или php://для чтения и записи в/из архива.
См. http://php.net/manual/en/wrappers.php.php
Ответ 3
Относительно вашего комментария, что php://temp работает для вас, за исключением случаев, когда вы его закрываете, попробуйте оставить его открытым, очистить вывод, а затем перемотать назад на 0 и прочитать его.
Посмотрите еще несколько примеров: http://us.php.net/manual/en/function.tmpfile.php
Также буферизация и захват результатов исследования: http://us.php.net/manual/en/function.ob-start.php
Ответ 4
Вам нужно использовать ZipArchive::addFromString
- если вы используете addFile()
, файл фактически не добавляется, пока вы не закроете его. (Ужасная ошибка IMHO, что, если вы пытаетесь переместить файлы в zip, и вы удаляете их, прежде чем закрыть zip...)
Метод addFromString()
немедленно добавляет его в архив.
Ответ 5
Есть ли проблема производительности здесь, или это просто оскорбляет ваше чувство правильности? Многие процессы записывают временные файлы и удаляют их, и часто они никогда не попадают на диск из-за кэширования.
Временной файл автоматически удаляется при закрытии. Это его природа.
Есть только два способа создать zip файл в памяти и обслуживать его, и оба они, вероятно, больше проблем, чем они того стоят.
- используйте диск.
- измените класс ziparchive, чтобы добавить метод, который делает все, что делает метод close(), кроме фактически закрыть файл. (Или добавьте параметр отпускания для закрытия()).
Это может быть даже невозможно в зависимости от базовых библиотек C.