Подтвердить что ты не робот

Манипулировать архивом в памяти с помощью PHP (без создания временного файла на диске)

Я пытаюсь создать архив на лету в PHP и немедленно отправить его пользователю (не сохраняя его). Я решил, что нет необходимости создавать файл на диске, поскольку данные, которые я отправляю, в любом случае не постоянны, однако при поиске в Интернете я не мог понять, как это сделать. Мне также не нужен формат файла.

Итак, вопрос:

Возможно ли создать и обработать файловый архив в памяти в php script без создания временного файла на этом пути?

4b9b3361

Ответ 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.