Zumbe.net

Comenzando a programar una web

Crear archivos ZIP y TAR al vuelo con PHP(Direcciones relativas)

De modo que tenemos que encontrar una solución para esto. La solución más sencilla es copiar todos los archivos y directorios al directorio temporal, de modo que las direcciones relativas sean correctas. Copiar un archivo es fácil, ya que PHP viene con una función innata de copia, llamada lógicamente copy(). Tenemos que añadir lo siguiente a nuestro script:

Código: php
  1. <?php
  2. foreach ($list as $item) {
  3.         if (is_file($item)) {
  4.                 // Copiar archivo
  5.                 copy ($item, $dir . $item);
  6.         } elseif (is_dir ($item)) {
  7.                 // TAREA: haremos esto en un minuto
  8.         } else {
  9.                 // Archivo no válido, símplemente ignorar
  10.                 continue;
  11.         }
  12. }
  13. ?>

Si colocamos el código anterior encima de la llamada a chdir(), todos los archivos se incluirán en nuestro archivo zip, y funcionará correctamente. Pero los directorios no se han incluido todabía, porque no los hemos copiado.

Desafortunadamente PHP no viene con una función del tipo copy_directory(), y tenemos que escribir la nuestra propia. Echando un ojo a Google seguramente encontraremos algo rápidamente, pero aquí tenéis uno que he escrito yo mismo:

Código: php
  1. <?php
  2.      function move_directory($source, $dest, $copy=false) {
  3.     // Igualar direcciones
  4.     $source = str_replace(, ‘/’, $source);
  5.     $source = str_replace(, ‘/’, $source);
  6.  
  7.     $dest = str_replace(, ‘/’, $dest);
  8.     $dest = str_replace(, ‘/’, $dest);
  9.  
  10.     // Eliminar barras finales
  11.     $source = rtrim($source, ‘/’);
  12.     $dest = rtrim($dest, ‘/’);
  13.  
  14.     // Añadir barras finales
  15.     $source .= ‘/’;
  16.     $dest .= ‘/’;
  17.  
  18.     // El archivo no existe?
  19.     if (file_exists($source) == false) { return false; }
  20.  
  21.     // Intenta crear el destino
  22.     @mkdir($dest);
  23.  
  24.     // El destino no existe?
  25.     if (file_exists($dest) == false) { return false; }
  26.  
  27.     // Copiar todos los archivos
  28.     $d = dir($source);
  29.  
  30.     while (false !== ($entry = $d->read())) {
  31.             if ($entry == ‘.’ OR $entry == ‘..’) continue;
  32.             $file = $d->path . $entry;
  33.  
  34.             // Es un sub directorio?
  35.             if (is_dir($file)) {
  36.                     // Intenta crear un subdirectorio
  37.                     $subdir = $dest . $entry . ‘/’;
  38.                     $result = @mkdir($subdir);
  39.                     if ($result == false) { continue; }
  40.  
  41.                     // Mover los archivos al subdirectorio
  42.                     move_directory($file, $subdir, $copy);
  43.                     continue;
  44.             }
  45.  
  46.             // Copiar archivo
  47.             copy($file, $dest . $entry);
  48.  
  49.             // Eliminar archivo antiguo?
  50.             if ($copy == false) {
  51.                     // Eliminar el directorio original
  52.                     @unlink($file);
  53.             }
  54.     }     
  55.  
  56.     if ($copy == false) {
  57.             @rmdir($source);
  58.     }
  59.  
  60.     return true;
  61. }
  62. ?>

No voy a explicar la función completa, pero básicamente copia todos los archivos en el directorio, y todos los subdirectorios (y lo mismo hasta cuatro veces).

Si añadimos esta función a nuestro script, la parte que copia los archivos y directorios ahora tiene esta pinta:

Código: php
  1. <?php
  2. foreach ($list as $item) {
  3.         if (is_file($item)) {
  4.                 // Copiar archivo
  5.                 copy ($item, $dir . $item);
  6.         } elseif (is_dir ($item)) {
  7.                 // Copiar directorio
  8.                 move_directory ($item, $dir . $item, true);
  9.         } else {
  10.                 // Archivo no válido, símplemente ignorar
  11.                 continue;
  12.         }
  13. }
  14. ?>

Y si lo unimos todo, nuestro script será algo como esto:

Código: php
  1. <?php
  2. include (‘pear/archive_zip.php’);
  3.  
  4. // Crear la instancia de la clase Archive_Zip e introducir el nombre de nuestro archivo zip
  5. $zipfile = New Archive_Zip(‘myzipfile.zip’);
  6.  
  7. // Crear una lista de archivos y directorios
  8. $list = array(‘example.txt’);
  9.  
  10. // Obtener el directorio temporal
  11. if (!empty($_ENV[‘TMP’])) {
  12.         $tempdir = $_ENV[‘TMP’];
  13. } elseif (!empty($_ENV[‘TMPDIR’])) {
  14.         $tempdir = $_ENV[‘TMPDIR’];
  15. } elseif (!empty($_ENV[‘TEMP’])) {
  16.         $tempdir = $_ENV[‘TEMP’];
  17. } else {
  18.         $tempdir = dirname(tempnam(, ‘na’));
  19. }
  20.  
  21. if (empty($tempdir)) { die (‘No hay directorio temporal’); }
  22.  
  23. // Nos aseguramos de que acabe en barra lateral
  24. $tempdir = rtrim($tempdir, ‘/’);
  25. $tempdir .= ‘/’;
  26.  
  27. // Nos aseguramos de que tiene permisos de escritura
  28. if (is_writable($tempdir) == false) {
  29.         die (‘El directorio temporal no tiene permisos de escritura’);
  30. }
  31.  
  32. // Crear un nombre temporal para nuestro directorio
  33. $dir = tempnam($tempdir, ‘temp’);
  34.  
  35. // Nos aseguramos de que no hay otro archivo o directorio con ese nombre
  36. @unlink($dir);
  37. @rmdir($dir);
  38.  
  39. // Creamos el directorio
  40. mkdir($dir);
  41. $dir .= ‘/’;
  42.  
  43. // Copiar los archivos y directorios para que funcionen las direcciones relativas
  44. foreach ($list as $item) {
  45.     if (is_file($item)) {
  46.             // Copiar archivo
  47.             copy ($item, $dir . $item);
  48.     } elseif (is_dir ($item)) {
  49.             // Copiar directorio
  50.             move_directory ($item, $dir . $item, true);
  51.     } else {
  52.             // Archivo no válido, símplemente ignorar
  53.             continue;
  54.     }
  55. }
  56.  
  57. // Cambiamos el directorio de trabajo actual para que el archivo zip se cree en el directorio temporal
  58. chdir($dir);
  59.  
  60. // Crear el archivo zip
  61. $zipfile->create($list);
  62.  
  63. echo ‘Archivo zip creado en  ‘ . $dir;
  64.  
  65. function move_directory($source, $dest, $copy=false) {
  66.     // Igualar direcciones
  67.     $source = str_replace(, ‘/’, $source);
  68.     $source = str_replace(, ‘/’, $source);
  69.  
  70.     $dest = str_replace(, ‘/’, $dest);
  71.     $dest = str_replace(, ‘/’, $dest);
  72.  
  73.     // Eliminar barras finales
  74.     $source = rtrim($source, ‘/’);
  75.     $dest = rtrim($dest, ‘/’);
  76.  
  77.     // Añadir barras finales
  78.     $source .= ‘/’;
  79.     $dest .= ‘/’;
  80.  
  81.     // El archivo no existe?
  82.     if (file_exists($source) == false) { return false; }
  83.  
  84.     // Intenta crear el destino
  85.     @mkdir($dest);
  86.  
  87.     // El destino no existe?
  88.     if (file_exists($dest) == false) { return false; }
  89.  
  90.     // Copiar todos los archivos
  91.     $d = dir($source);
  92.  
  93.     while (false !== ($entry = $d->read())) {
  94.             if ($entry == ‘.’ OR $entry == ‘..’) continue;
  95.             $file = $d->path . $entry;
  96.  
  97.             // Es un sub directorio?
  98.             if (is_dir($file)) {
  99.                     // Intenta crear un subdirectorio
  100.                     $subdir = $dest . $entry . ‘/’;
  101.                     $result = @mkdir($subdir);
  102.                     if ($result == false) { continue; }
  103.  
  104.                     // Mover los archivos al subdirectorio
  105.                     move_directory($file, $subdir, $copy);
  106.                     continue;
  107.             }
  108.  
  109.             // Copiar archivo
  110.             copy($file, $dest . $entry);
  111.  
  112.             // Eliminar archivo antiguo?
  113.             if ($copy == false) {
  114.                     // Eliminar el directorio original
  115.                     @unlink($file);
  116.             }
  117.     }     
  118.  
  119.     if ($copy == false) {
  120.             @rmdir($source);
  121.     }
  122.  
  123.     return true;
  124. }
  125.  
  126. ?>

Y esto es básicamente lo que necesitamos

(En el tutorial original continúa dos puntos más.)

23 Octubre 2006 · Tags Sin categoría |

3 Comentarios

marcelo dice:

Me parece excelente el tutorial excepto por un par de problemas que se me presentaron al utilizar el codigo.

Las rutas relativas NO FUNCIONAN, solamente funcionan aquellas rutas relativas que sean de la forma ../example.txt ó ../../example.txt ó ./example.txt.

Si utilizo rutas como las siguientes:
./ejemplo/example.txt
../ejemplo/example.txt
da un error cuando tiene se utiliza la funcion copy() de PHP. Una verdadera lastima ya que el código esta buenisimo pero ese problema me obliga a tener q reverlo todo de nuevo e intentar una solucion que si se adecue a estas rutas. Si alguien descubre o ya sabe como solucionarlo me encantaria que me lo hiciera llegar, ya que no dispongo del tiempo como para ponerme a solucionarlo.

Desde ya gracias.


7 de Junio del 2007 a las 23:25
admin dice:

Lo siento mucho. Como explico en el tutorial, en este caso yo soy el traductor, el redactor es la página PHPit.net

Si tienes alguna consulta te recomiendo que visites el atrículo original y preguntes (en inglés) http://www.phpit.net/article/creating-zip-tar-archives-dynamically-php/

Un saludo, y muchas gracias por visitar Zumbe.


8 de Junio del 2007 a las 0:09
Lucas dice:

Disculpa che… la verdad segui el tutorial y no me salio

srry


6 de Septiembre del 2007 a las 20:16

Escribe un comentario!

Buscador

2005-2007 Zumbe.net Creada por Alex Barros con WordPress - Licencia Reconocimiento - RSS