Archivos zip con php (notas)

Unas notas sobre el trabajo de archivos zip con php

Koscha

archivado en: PHP/AJAX / 1 noviembre, 2013

post in progress

Hay varias maneras de preparar un archivo zip con PHP. La más sencilla es emplear la clase zipArchive.

El mecanismo básico es muy simple:

// Sacamos una instancia de ZipArchive

$miInstanciaZip = new ZipArchive();

// Le ponemos un nombre

$nombreZip = "archivo.zip";

/* Creamos el archivo con el método open, al que le pasamos el nombre
como primer parámetro y la constante ZipArchive::CREATE como segundo */

$miInstanciaZip->open($nombreZip, ZipArchive::CREATE);

// Añadimos los archivos a comprimir, por ejemplo, una imagen del directorio imagenes
$miInstanciaZip->addFile("imagenes/miarchivo.jpg");

// Cerramos el zip

$miInstanciaZip->close();

Y con eso ya tendríamos un archivo zip en el directorio que hemos lanzado el script llamado archivo.zip.

Veamos ahora el proceso con más detalle.

open (notas)

a) En teoría, aquí podríamos definir dos maneras principales para crear el archivo, con CREATE y con OVERWRITE

$miInstanciaZip->open($nombreZip, ZipArchive:::OVERWRITE);

Se supone que solo de la segunda manera se debería pisar el archivo en caso de que ya exista, pero con CREATE también lo sobreescribimos (bueno, en realidad, le añadimos elementos).  Un apaño si no queremos pisar un zip existente es comprobar si existe el archivo con is_file().

if (  is_file($nombreZip)  ) {

die("El archivo ya existe");

}

b) open() devuelve true (1) si ha funcionado...

$preparaZip = $miInstanciaZip->open($nombreZip, ZipArchive::CREATE);

echo $preparaZip; // 1

lo que nos permite lanzar el resto de operaciones solo en el caso de que todo haya ido bien (1). Algo así...

if ( $miInstanciaZip->open($nombreZip, ZipArchive::CREATE) == 1 ) {

// Aquí el resto del script...

}

addFile (notas)

a) Podemos cambiar el nombre del archivo que estamos comprimiendo indicándolo en el segundo parámetro.

$miInstanciaZip->addFile("imagenes/miarchivo.jpg", "nuevoDirectorio/nuevoNombre,jpg");

b) No existe una manera sencilla de comprimir todo el contenido de un directorio en el caso de que existan subdirectorios o varios archivos. Al menos que yo conozca.

Javier Angosto propone una forma elegante de conseguirlo aprovechando las posibilidades de scandir, que lista el contenido de un directorio, volviendo a llamar a una función que añade el archivo en el caso de que sea un directorio. Sin sus comentarios, algo así:

$nombreZip = "archivo.zip";

$directorioaComprimir = "imagenes";

$miInstanciaZip = new ZipArchive();

if ( $miInstanciaZip->open($nombreZip, ZIPARCHIVE::CREATE) ) {

comprimirDirectorio($directorioaComprimir, $miInstanciaZip);

$miInstanciaZip->close();

}
function comprimirDirectorio($directorio, $miInstanciaZip) {

if ( is_dir($directorio) ) {

foreach (scandir($directorio) as $elemento) {

if ($elemento == '.' || $elemento == '..') continue;

comprimirDirectorio($directorio . "/" . $elemento, $miInstanciaZip);

}

} else {

$miInstanciaZip->addFile($directorio);

}

}

Descomprimir archivos

Para descomprimir archivos zip podemos emplear el método extractTo, al que se le envía el destino del archivo que estamos deszipeando.

// Abrimos el archivo y si existe lo descomprimimos.

if ( $miInstanciaZip->open($nombreZip) ) {

$miInstanciaZip->extractTo('archivoDescomprimido');

$miInstanciaZip->close();

}

Descargas temporales

En el manual, también han incluido un ejemplo para que la descarga sea de un archivo temporal, el cual destruimos una vez enviado al usuario. No funciona en local y hay que tener cuidado con no dejar espacio en blanco alguno antes de la etiqueta de apertura.

// Creamos un archivo temporal

$file = tempnam(sys_get_temp_dir(), "zip");

// Sacamos una instancia de ZipArchive

$zip = new ZipArchive();

// Preparamos el zip

$zip->open($file, ZipArchive::OVERWRITE);

$zip->addFile("imagenes/miarchivo.jpg");

$zip->close();

// Lo enviamos

header("Content-Type: application/zip");

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

header("Content-Disposition: attachment; filename=\"archivoParaDescargar.zip\"");

readfile($file);

unlink($file);

Bueno, tengo pendiente ordenar todo este batiburrillo en una clase.

Notas

1.  Si los archivos a comprimir muy pesados, puede resultar más interesante realizar el proceso en Linux. La sintaxis básica es: zip nombreDelZip RutaAEmpaquetar

Sin embargo, si nos queremos saltar el árbol de directorios (con -j no sirve) hasta la ruta del directorio a empaquetar, antes debemos situarnos en ese directorio. Algo así:

$rutaBase = $_SERVER['DOCUMENT_ROOT'].'/resto de la ruta';

$command = "cd ".$rutaBase."/empaquetado/;  nice -n19 zip -r9 ./nombreZip.zip *";

exec($command);

2. En el manual, un tal saulius propone una función muy chula para mostrar el error que se pueda haber producido con el método open.

function zipFileErrMsg($errno) {

// using constant name as a string to make this function PHP4 compatible

$zipFileFunctionsErrors = array(

'ZIPARCHIVE::ER_MULTIDISK' => 'Multi-disk zip archives not supported.',

'ZIPARCHIVE::ER_RENAME' => 'Renaming temporary file failed.',

'ZIPARCHIVE::ER_CLOSE' => 'Closing zip archive failed',

'ZIPARCHIVE::ER_SEEK' => 'Seek error',

'ZIPARCHIVE::ER_READ' => 'Read error',

'ZIPARCHIVE::ER_WRITE' => 'Write error',

'ZIPARCHIVE::ER_CRC' => 'CRC error',

'ZIPARCHIVE::ER_ZIPCLOSED' => 'Containing zip archive was closed',

'ZIPARCHIVE::ER_NOENT' => 'No such file.',

'ZIPARCHIVE::ER_EXISTS' => 'File already exists',

'ZIPARCHIVE::ER_OPEN' => 'Can\'t open file',

'ZIPARCHIVE::ER_TMPOPEN' => 'Failure to create temporary file.',

'ZIPARCHIVE::ER_ZLIB' => 'Zlib error',

'ZIPARCHIVE::ER_MEMORY' => 'Memory allocation failure',

'ZIPARCHIVE::ER_CHANGED' => 'Entry has been changed',

'ZIPARCHIVE::ER_COMPNOTSUPP' => 'Compression method not supported.',

'ZIPARCHIVE::ER_EOF' => 'Premature EOF',

'ZIPARCHIVE::ER_INVAL' => 'Invalid argument',

'ZIPARCHIVE::ER_NOZIP' => 'Not a zip archive',

'ZIPARCHIVE::ER_INTERNAL' => 'Internal error',

'ZIPARCHIVE::ER_INCONS' => 'Zip archive inconsistent',

'ZIPARCHIVE::ER_REMOVE' => 'Can\'t remove file',

'ZIPARCHIVE::ER_DELETED' => 'Entry has been deleted',

);

$errmsg = 'unknown';

foreach ($zipFileFunctionsErrors as $constName => $errorMessage) {

if (defined($constName) and constant($constName) === $errno) {

return 'Zip File Function error: '.$errorMessage;

}

}

return 'Zip File Function error: unknown';

}
$nombreZip = "archivo.zip";

$directorioaComprimir = "imageness";

$zip = new ZipArchive();

$zip = zip_open($nombreZip);

if (!is_resource($zip)) {

die(zipFileErrMsg($zip));

}

// Zip File Function error: Can't open file (no encuentra el directorio a comprimir)

|| Tags:

valoración de los lectores sobre Archivos zip con php (notas)

  • estrellica valoración positiva
  • estrellica valoración positiva
  • estrellica valoración positiva
  • estrellica valoración positiva
  • estrellica valoración negativa
  • 4.3 sobre 5 (7 votos)

¿Te ha parecido útil o interesante esta entrada?
dormido, valoración 1 nadapensativo, valoración 2 un poco sonrisa, valoración 3 a medias guiño, valoración 4 bastante aplauso, valoración 5 mucho

Tú opinión es muy importante, gracias por compartirla!

Los comentarios están cerrados.