2009-07-27 25 views
26

Estoy tratando de generar un archivo sobre la marcha en PHP y enviarlo al usuario de inmediato (sin guardarlo). Pensé que no habría necesidad de crear un archivo en el disco ya que los datos que estoy enviando no son persistentes de todos modos, sin embargo, al buscar en la web, no pude averiguar cómo. Tampoco me importa el formato de archivo.Manipular un archivo en la memoria con PHP (sin crear un archivo temporal en el disco)

Entonces, la pregunta es:

¿Es posible crear y manipular un archivo de almacenamiento en memoria dentro de un script php sin crear un archivo temporal en el camino?

+0

¿Puede este archivo contener solo un archivo o más de un archivo? – VolkerK

+0

En mi caso específico, contiene más de uno. también pensaría que una solución de "arbitraria" grandes archivos (punto-wise) es mucho más interesante (en mi caso, puedo utilizar un archivo temporal, pero ¿qué pasa con las personas que tienen que utilizar un servidor al que se acceda a la el sistema de archivos está restringido)? – ralokt

Respuesta

42

Tuve el mismo problema pero finalmente encontré una solución algo oscura y decidí compartirla aquí.

Encontré los grandes scripts zip.lib.php/unzip.lib.php que vienen con phpmyadmin y se encuentran en el directorio "libraries".

Usando zip.lib.php trabajó como un encanto para mí:

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(); 

Este script permite la descarga de una cremallera, sin la necesidad de tener los archivos como archivos reales o guardar la cremallera a sí misma como un archivo.

Es una pena que esta funcionalidad no es parte de una librería PHP más genérico.

Aquí hay un enlace al archivo zip.lib.php de la fuente de phpMyAdmin: https://github.com/phpmyadmin/phpmyadmin/blob/RELEASE_4_5_5_1/libraries/zip.lib.php

ACTUALIZACIÓN: Asegúrese de retirar la siguiente comprobación desde el comienzo de zip.lib.php lo contrario el guión acaba termina:

if (! defined('PHPMYADMIN')) { 
    exit; 
} 

ACTUALIZACIÓN: Este código está disponible en el proyecto CodeIgniter así: https://github.com/patricksavalle/CodeIgniter/blob/439ac3a87a448ae6c2cbae0890c9f672efcae32d/system/helpers/zip_helper.php

+0

se debe mencionar que es necesario modificarlo para eliminar la marca de la definición de la 'PHPMYADMIN' constante, o se terminará el guión. Me llevó más de un segundo resolverlo. – Nathaniel

+0

Gracias, parece que el cheque se introdujo después de publicar el anterior responder. Actualicé la respuesta. – nettle

+0

Funciona como un encanto. Hice esto en un Codeigniter helper sin ningún problema. –

3

¿qué estás utilizando para generar el archivo? Es posible que pueda usar la secuencia php: // temp o php: // memory para leer y escribir en/desde el archivo.

Ver http://php.net/manual/en/wrappers.php.php

+1

Por el momento, estoy usando la extensión zip php y escribiendo un archivo temporal cada vez que publico una descarga. He intentado utilizar la envoltura php: // temp (pensando que era superior a php: // memoria, al igual que con grandes cantidades de datos, un archivo temporal es una buena idea, y los anfitriones podría permitir su uso, incluso mientras se restringe el acceso fs . Me encontré con el problema que tuve que cerrar el archivo zip, que al parecer liberó todo en php: // temp /. (Leer desde el archivo zip antes y después del cierre me dio 0 bytes) De todos modos, no lo hago t se preocupan por la biblioteca de uso, siempre y cuando funciona. PHP-interno sería preferible, por supuesto. – ralokt

-7

¿Hay realmente un problema de rendimiento aquí, o solo ofende su sentido de rectitud? Muchos procesos escriben archivos temporales y los eliminan, y con frecuencia nunca llegan al disco debido al almacenamiento en caché.

Un archivo temporal se elimina automáticamente cuando se cierra. Esa es su naturaleza.

Solo hay dos formas en que puedo pensar para crear un archivo zip en la memoria y servirlo, y ambos son probablemente más problemas de los que merecen.

  • utilice un disco ram.
  • modifica la clase ziparchive para agregar un método que hace todo lo que hace el método close(), excepto en realidad cierra el archivo. (O agregue un parámetro de dejar abierto para cerrar()).
    Esto incluso podría no ser posible dependiendo de las bibliotecas C subyacentes.
0

Es necesario utilizar ZipArchive::addFromString - si utiliza addFile() en realidad no se añadió el archivo hasta que se vaya a cerrarla. (Horrible error en mi humilde opinión, ¿qué pasa si estás tratando de mover archivos a un archivo comprimido y los borras antes de cerrar el zip ...)
El método addFromString() lo agrega al archivo de inmediato.

Cuestiones relacionadas