Comprimir un directorio completo en zip desde php
|Este es un complemento de Como crear un archivo zip desde php donde agregabamos archivo por archivo al zip, en cambio la forma que les voy a presentar a continuación se puede comprimir un directorio entero incluyendo subdirectorios y archivos dentro de directorios. En este ejemplo también estamos utilizando ZipArchive.
Este es el código junto con los respectivos comentarios:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
<?php /* primero creamos la función que hace la magia * esta funcion recorre carpetas y subcarpetas * añadiendo todo archivo que encuentre a su paso * recibe el directorio y el zip a utilizar */ function agregar_zip($dir, $zip) { //verificamos si $dir es un directorio if (is_dir($dir)) { //abrimos el directorio y lo asignamos a $da if ($da = opendir($dir)) { //leemos del directorio hasta que termine while (($archivo = readdir($da)) !== false) { /*Si es un directorio imprimimos la ruta * y llamamos recursivamente esta función * para que verifique dentro del nuevo directorio * por mas directorios o archivos */ if (is_dir($dir . $archivo) && $archivo != "." && $archivo != "..") { echo "<strong>Creando directorio: $dir$archivo</strong><br/>"; agregar_zip($dir . $archivo . "/", $zip); /*si encuentra un archivo imprimimos la ruta donde se encuentra * y agregamos el archivo al zip junto con su ruta */ } elseif (is_file($dir . $archivo) && $archivo != "." && $archivo != "..") { echo "Agregando archivo: $dir$archivo <br/>"; $zip->addFile($dir . $archivo, $dir . $archivo); } } //cerramos el directorio abierto en el momento closedir($da); } } } //fin de la función //creamos una instancia de ZipArchive $zip = new ZipArchive(); /*directorio a comprimir * la barra inclinada al final es importante * la ruta debe ser relativa no absoluta */ $dir = 'fuente/'; //ruta donde guardar los archivos zip, ya debe existir $rutaFinal = "archivos"; if(!file_exists($rutaFinal)){ mkdir($rutaFinal); } $archivoZip = "kiuvox.zip"; if ($zip->open($archivoZip, ZIPARCHIVE::CREATE) === true) { agregar_zip($dir, $zip); $zip->close(); //Muevo el archivo a una ruta //donde no se mezcle los zip con los demas archivos rename($archivoZip, "$rutaFinal/$archivoZip"); //Hasta aqui el archivo zip ya esta creado //Verifico si el archivo ha sido creado if (file_exists($rutaFinal. "/" . $archivoZip)) { echo "Proceso Finalizado!! <br/><br/> Descargar: <a href='$rutaFinal/$archivoZip'>$archivoZip</a>"; } else { echo "Error, archivo zip no ha sido creado!!"; } } ?> |
Ejemplo del resultado
20 comentarios
muy buen aporte, felicitaciones
Hola, gracias por compartir esta función que resulta muy útil para hacer respaldos, pero creo que debo hacer algo mal ya que no corre, tal vez debido a que no esta habilitada la clase ZipArchive, me podrías decir como debe de aparecer habilitada en el php.ini? Puede ser que no la tenga por que no instale el paquete a la hora de instalar php7 en mi linux mint . Gracias por todo
Gracias, si era eso, y lo solucione con estas dos lineas, lo pongo por si dudaban que corriera,
sudo apt-get install php7.0-zip
sudo apt-get install php7.0-gd
corre perfecto, gracias.
Muchas gracias por tu aporte, que bueno que lo resolviste en poco tiempo.
Hola, si quisiera que se ejecutara todo esto cuando apretara el boton descargar archivo en vez de automáticamente al cargar la pagina como seria?. gracias
Simon, lo que tenes que hacer es primero crear un formulario sencillo donde el action apunte al archivo que genera el archivo comprimido. Ej:
Luego del codigo php de este post vamos a cambiar el final del archivo, en lugar de presentar el enlace al archivo zip vamos a escribir unos header que fuercen a la descarga del archivo comprimido. Entonces sustituye este código:
Por este:
Esto debería funcionar según la prueba que acabo de realizar, espero que eso te ayude. Saludos.
Gracias por contestar tan rápido,
Hice los cambios que me comentaste pero al cargar la pagina donde se encuentra el codigo del form me sale todo un texto lleno de ? con fondo negro y finaliza dandome error.
Se me ocurre que talvez tengas alguna sintaxis mal escrita, porque ese html de prueba que puse no sale nada más que un botón que dice Descargar, sin fondo ni nada de eso. Habría que revisar tu código para estar seguro.
Excelente material, pero tengo un pequeño inconveniente y es que no incluye los directorios que están vacíos, alguna idea de como solucionarlo?
Me da pena responder hasta este momento, pero espero que entiendan que la vida del informático es precararia de tiempo libre cuando hay varios proyectos pendientes por realizar.
La verdad no me había dado cuenta que el script no incluia los directorios vacío en el zip, para incluirlos podemos crear los directorios por anticipado antes de añadir los archivos.
Al script que ya este hecho podemos agregar una línea de código para hacerlo.
Primero ubicamos esta fila:
Justo arriba de esa linea añadimos esta:
Con esto estarémos creando las carpetas por anticipado antes de incluir los archivos si hay alguno.
Si es por respuesta fuera de tiempo la mía se supera ahora, no sé si la vas a ver pero quería agradecerte por responder, sé como es cuando hay muchos proyectos y nada de tiempo.
Espero que a alguien más le sirva esto así como me sirvio a mi.
Saludos.
Hace cerca de un año esta publicación tuya me simplificó la vida para una tarea que tuve asignada.
Te comparto la «derivada» de tu función a una clase PHP.
http://xpcid.com/php-zip-de-carpeta.php
Saludos,
Olvide mencionar lo más importante:
Agradezco tu publicación.
En serio me simplificó un montón la vida.
Hola, gracias por el post.
Cómo haría para que no me agregue las carpetas anteriores a la que quiero compilar?
Muchas gracias.
esta linea:
$zip->addFile($dir . $archivo, $dir . $archivo);
la modificas así:
$zip->addFile($dir . $archivo, $archivo);
Excelente explicación.
Una pregunta, en caso de que la yo cierre el archivo .php que está haciendo la compresión antes de que esta termine
¿Que pasaría?
¿Se cancela la compresión?
Gracias de antemano.
Pues el procedimiento quedaría inconcluso, no llegaría a completarse el zip ni sería cerrado, por ende no llegaría a formarse como un archivo .zip si me doy a entender.
Muchas gracias. Enhorabuena por la magnífica aportación.
De entrada muchísimas gracias por publicar tu script, esta función es muy efectiva.
Lo único que me gustaría saber es si se pueden vaciar todos los archivos a un sólo nivel del ZIP… vaya, que no se genere todo el árbol de rutas dentro del ZIP.
Me respondo a mi mismo XD
esta linea:
$zip->addFile($dir . $archivo, $dir . $archivo);
la modificas así:
$zip->addFile($dir . $archivo, $archivo);