2009-06-30 14 views
40

¿Cuál es la forma más fácil de comprimir, digamos 2 archivos, desde una carpeta en el servidor y forzar la descarga? Sin guardar el "zip" en el servidor.Archivos ZIP de PHP sobre la marcha

$zip = new ZipArchive(); 
    //the string "file1" is the name we're assigning the file in the archive 
$zip->addFile(file_get_contents($filepath1), 'file1'); //file 1 that you want compressed 
$zip->addFile(file_get_contents($filepath2), 'file2'); //file 2 that you want compressed 
$zip->addFile(file_get_contents($filepath3), 'file3'); //file 3 that you want compressed 
echo $zip->file(); //this sends the compressed archive to the output buffer instead of writing it to a file. 

se puede verificar: Tengo una carpeta con Test1.doc, Test2.doc y test3.doc

con el ejemplo anterior - fichero1 (archivo2 y archivo3) sólo podría ser Test1.doc , etc.

¿Tengo que hacer algo con "$ filepath1"? ¿Es ese el directorio de carpetas que contiene los 3 documentos?

Lo siento por mi pregunta básica ..

+0

De acuerdo con la [documentación] (http://us3.php.net/manual/en/class.ziparchive.php) la clase ZipArchive no tiene ningún archivo de función() y esto dará como resultado un error. Para hacer esto necesita una biblioteca diferente como por ejemplo [este] (http://stackoverflow.com/questions/1189019/manipulate-an-archive-in-memory-with-php-without-creating-a- temporal-archivo-en-d). Solo ponerlo aquí para que otras personas no pasen horas intentando que esto funcione con las sugerencias a continuación. – Neograph734

Respuesta

4

Si tiene acceso a la utilidad de compresión de comandos puede intentar

<?php 
$zipped_data = `zip -q - files`; 
header('Content-type: application/zip'); 
header('Content-Disposition: attachment; filename="download.zip"'); 
echo $zipped_data; 
?> 

donde los archivos son las cosas que desea comprimir y postal de la ubicación de la cremallera ejecutable.

Esto asume Linux o similar, por supuesto. En Windows, es posible que pueda hacer algo similar con otra herramienta de compresión, supongo.

También hay un zip extension, el uso se muestra here.

+0

Edita tu pregunta con el error que obtienes. El primer sospechoso es que no tiene instalada la extensión zip. –

9

Su código está muy cerca. Necesita usar el nombre del archivo en lugar del contenido del archivo.

$zip->addFile(file_get_contents($filepath1), 'file1'); 

debería ser

$zip->addFile($filepath1, 'file1'); 

http://us3.php.net/manual/en/function.ziparchive-addfile.php

Si es necesario agregar archivos de una variable en lugar de un archivo que puede utilizar la función AddFromString.

$zip->addFromString('file1', $data); 
+0

Estoy de acuerdo con esto, pero necesita usar algo como dice Vinko al forzar un encabezado para que el navegador descargue. – m4rc

61

Desafortunadamente w/PHP 5.3.4-dev y v2.3.0 Motor Zend en CentOS 5.x no pude conseguir el código anterior para trabajar. Un mensaje de error "Válido o unificado de objeto postal" fue todo lo que pude obtener. Por lo tanto, con el fin de hacer que funcione, tuve que usar siguiente fragmento (tomado del ejemplo de Jonathan Baltazar en el manual de PHP.net, en el ZipArchive :: página abierta):

// Prepare File 
$file = tempnam("tmp", "zip"); 
$zip = new ZipArchive(); 
$zip->open($file, ZipArchive::OVERWRITE); 

// Stuff with content 
$zip->addFromString('file_name_within_archive.ext', $your_string_data); 
$zip->addFile('file_on_server.ext', 'second_file_name_within_archive.ext'); 

// Close and send to users 
$zip->close(); 
header('Content-Type: application/zip'); 
header('Content-Length: ' . filesize($file)); 
header('Content-Disposition: attachment; filename="file.zip"'); 
readfile($file); 
unlink($file); 

Sé que esto es diferente que trabajar solo con memoria, a menos que tengas tu área de tmp en ram ;-) - pero quizás esto pueda ayudar a alguien más, que está luchando con la solución anterior, como yo; y por lo que la penalización de rendimiento no es un problema.

+0

esto me ayudó hoy, gracias. cuando se trata de un sistema admin/cms que genera archivos PDF sobre la marcha, el rendimiento es secundario al comprimir todos los archivos juntos, así que no tengo que inundar el administrador con 15 diálogos de descarga :) – jammypeach

+0

¿Alguien sabe si puede haber problemas? con eliminar el archivo justo después de leerlo en el búfer de salida? ¿O es ese enfoque a prueba de balas? –

3

Respuesta de maraspin es lo que probé. Extrañamente, tengo trabajo mediante la eliminación de la línea de cabecera que hace referencia al tamaño de archivo:

header('Content-Length: ' . filesize($file)); 

Con el cambio anterior, el código funciona como una brisa! Sin este cambio, recibí el siguiente mensaje de error:

Fin de la firma del directorio central no encontrada. O bien este archivo no es un archivo zip, o constituye un disco de un archivo de varias partes.En este último caso, el directorio central y el comentario del archivo zip se encontrarán en los últimos discos de este archivo.

entorno de prueba:

OS: Ubuntu 10.10 Navegador: Firefox y la pila por defecto LAMP.

+0

Hallelujah !!!!! – Stevo

+0

El encabezado es "Content-Length" y el tamaño del archivo, no la longitud, se estableció en él. ¿Tal vez por eso? – Parziphal

1

itsols Si desea insertar el 'Content-Length' lo hacen así:

$length = filesize($file); 
header('Content-Length: ' . $length); 

No sé por qué, pero se bloquea si lo pones en la misma línea.

Cuestiones relacionadas