Crear archivos ZIP comprimidos con PHP y ZLIB, al vuelo - Electronik-Pro, Informatica, Noticas,Wordpress,Facebook,Hacking,Programas,Hosting,Dominios

Crear archivos comprimidos, es otra de las tareas que vienen casi por seguro cuando se trabaja con enormes cantidades de registros y se desea exportar en archivos portables.

En este post mostraré el procedimiento que sigo para crear archivos comprimidos con Gzip, y una pequeña explicación de la clase que utilizo y sus razones:

PHP ofrece la posibilidad de crear archivoz Zip, pero deben ser configurados con diferentes dependencias según la version de PHP. Una de estas librerías es ZipArchive, el cual requiere bastantes dependencias por lo que no me centraré en esta clase (Aunque si alguien está interezado en utilizar esta clase, se podría decir que, la clase que explicaré en este post es una emulación de ZipArchive).

El código y parte de la explicación de esta clase está basado en la explicación que realizan en un artículo de zend.com: Éste clase utiliza el algoritmo de compresión ZLIB compression, que con ayuda de la función pack (que sirve para empaquetar datos en cadenas binarias), complementa la estructura de un archivo Zip. Para una explicación mas a fondo de como y por que lo hace, continuen leyendo en el artículo de zend: zend.com/.../creating-zip-files3 (en ingles).

El código de la clase es el siguiente:

El código de la clase es el siguiente:

  1. class zip{
  2. var $datasec = array();
  3. var $ctrl_dir = array();
  4. var $eof_ctrl_dir = "\x50\x4b\x05\x06\x00\x00\x00\x00";
  5. var $old_offset = 0;
  6. function add_dir($name) {
  7. $name = str_replace("", "/", $name);
  8. $fr = "\x50\x4b\x03\x04";
  9. $fr .= "\x0a\x00";
  10. $fr .= "\x00\x00";
  11. $fr .= "\x00\x00";
  12. $fr .= "\x00\x00\x00\x00";
  13. $fr .= pack("V",0);
  14. $fr .= pack("V",0);
  15. $fr .= pack("V",0);
  16. $fr .= pack("v", strlen($name) );
  17. $fr .= pack("v", 0 );
  18. $fr .= $name;
  19. $fr .= pack("V", 0);
  20. $fr .= pack("V", 0);
  21. $fr .= pack("V", 0);
  22. $this -> datasec[] = $fr;
  23. $new_offset = strlen(implode("", $this->datasec));
  24. $cdrec = "\x50\x4b\x01\x02";
  25. $cdrec .="\x00\x00";
  26. $cdrec .="\x0a\x00";
  27. $cdrec .="\x00\x00";
  28. $cdrec .="\x00\x00";
  29. $cdrec .="\x00\x00\x00\x00";
  30. $cdrec .= pack("V",0);
  31. $cdrec .= pack("V",0);
  32. $cdrec .= pack("V",0);
  33. $cdrec .= pack("v", strlen($name) );
  34. $cdrec .= pack("v", 0 );
  35. $cdrec .= pack("v", 0 );
  36. $cdrec .= pack("v", 0 );
  37. $cdrec .= pack("v", 0 );
  38. $ext = "\x00\x00\x10\x00";
  39. $ext = "\xff\xff\xff\xff";
  40. $cdrec .= pack("V", 16 );
  41. $cdrec .= pack("V", $this -> old_offset );
  42. $cdrec .= $name;
  43. $this -> ctrl_dir[] = $cdrec;
  44. $this -> old_offset = $new_offset;
  45. return;
  46. }
  47. function add_fileFromString($data,$name){
  48. $name = str_replace("", "/", $name);
  49. $unc_len = strlen($data);
  50. $crc = crc32($data);
  51. $zdata = gzcompress($data);
  52. $zdata = substr ($zdata, 2, -4);
  53. $c_len = strlen($zdata);
  54. $fr = "\x50\x4b\x03\x04";
  55. $fr .= "\x14\x00";
  56. $fr .= "\x00\x00";
  57. $fr .= "\x08\x00";
  58. $fr .= "\x00\x00\x00\x00";
  59. $fr .= pack("V",$crc);
  60. $fr .= pack("V",$c_len);
  61. $fr .= pack("V",$unc_len);
  62. $fr .= pack("v", strlen($name) );
  63. $fr .= pack("v", 0 );
  64. $fr .= $name;
  65. $fr .= $zdata;
  66. $fr .= pack("V",$crc);
  67. $fr .= pack("V",$c_len);
  68. $fr .= pack("V",$unc_len);
  69. $this -> datasec[] = $fr;
  70. $new_offset = strlen(implode("", $this->datasec));
  71. $cdrec = "\x50\x4b\x01\x02";
  72. $cdrec .="\x00\x00";
  73. $cdrec .="\x14\x00";
  74. $cdrec .="\x00\x00";
  75. $cdrec .="\x08\x00";
  76. $cdrec .="\x00\x00\x00\x00";
  77. $cdrec .= pack("V",$crc);
  78. $cdrec .= pack("V",$c_len);
  79. $cdrec .= pack("V",$unc_len);
  80. $cdrec .= pack("v", strlen($name) );
  81. $cdrec .= pack("v", 0 );
  82. $cdrec .= pack("v", 0 );
  83. $cdrec .= pack("v", 0 );
  84. $cdrec .= pack("v", 0 );
  85. $cdrec .= pack("V", 32 );
  86. $cdrec .= pack("V", $this -> old_offset );
  87. $this -> old_offset = $new_offset;
  88. $cdrec .= $name;
  89. $this -> ctrl_dir[] = $cdrec;
  90. }
  91. function add_file($data, $name) {
  92. $fp = fopen($data,"r");
  93. $data = fread($fp,filesize($data));
  94. fclose($fp);
  95. $name = str_replace("", "/", $name);
  96. $unc_len = strlen($data);
  97. $crc = crc32($data);
  98. $zdata = gzcompress($data);
  99. $zdata = substr ($zdata, 2, -4);
  100. $c_len = strlen($zdata);
  101. $fr = "\x50\x4b\x03\x04";
  102. $fr .= "\x14\x00";
  103. $fr .= "\x00\x00";
  104. $fr .= "\x08\x00";
  105. $fr .= "\x00\x00\x00\x00";
  106. $fr .= pack("V",$crc);
  107. $fr .= pack("V",$c_len);
  108. $fr .= pack("V",$unc_len);
  109. $fr .= pack("v", strlen($name) );
  110. $fr .= pack("v", 0 );
  111. $fr .= $name;
  112. $fr .= $zdata;
  113. $fr .= pack("V",$crc);
  114. $fr .= pack("V",$c_len);
  115. $fr .= pack("V",$unc_len);
  116. $this -> datasec[] = $fr;
  117. $new_offset = strlen(implode("", $this->datasec));
  118. $cdrec = "\x50\x4b\x01\x02";
  119. $cdrec .="\x00\x00";
  120. $cdrec .="\x14\x00";
  121. $cdrec .="\x00\x00";
  122. $cdrec .="\x08\x00";
  123. $cdrec .="\x00\x00\x00\x00";
  124. $cdrec .= pack("V",$crc);
  125. $cdrec .= pack("V",$c_len);
  126. $cdrec .= pack("V",$unc_len);
  127. $cdrec .= pack("v", strlen($name) );
  128. $cdrec .= pack("v", 0 );
  129. $cdrec .= pack("v", 0 );
  130. $cdrec .= pack("v", 0 );
  131. $cdrec .= pack("v", 0 );
  132. $cdrec .= pack("V", 32 );
  133. $cdrec .= pack("V", $this -> old_offset );
  134. $this -> old_offset = $new_offset;
  135. $cdrec .= $name;
  136. $this -> ctrl_dir[] = $cdrec;
  137. }
  138. function file() {
  139. $data = implode("", $this -> datasec);
  140. $ctrldir = implode("", $this -> ctrl_dir);
  141. return
  142. $data .
  143. $ctrldir .
  144. $this -> eof_ctrl_dir .
  145. pack("v", sizeof($this -> ctrl_dir)) .
  146. pack("v", sizeof($this -> ctrl_dir)) .
  147. pack("V", strlen($ctrldir)) .
  148. pack("V", strlen($data)) .
  149. "\x00\x00";
  150. }
  151. }
  152. ?>

Ésta clase contiene los siguiente métodos:

  • add_dir($name) - Éste método crea un directorio dentro del archivo zip.
  • add_file($data, $name) - Éste método lee un archivo, y lo guarda en el archivo zip.
  • add_fileFromString($data,$name) - Éste método lee un una cadena, y la guarda en el archivo que pasemos como parámetro dentro del zip.
  • file() - Éste método al ser llamado muestra el contenido del archivo zip. Éste debe ser utilizado para con el contenido que regrese crear un archivo con extensión zip, o para forzar al navegador a que el usuario descargue esa contenido y lo guarde con extensión zip.

Ahora, utilizarla. Es muy sencillo. 3 pasos: 1.- crear instancia de la clase, 2.- agregar información y 3.- crear el archivo zip o al navegador para que sea descargada.

Este ejemplo forza a la descarga directamente en el navegador:

  1. $zip = new zip();
  2. $zip->add_fileFromString("Esto es una prueba\n Estoy probando hola 1, 2, 3 probando... ", "prueba.txt");
  3. $zip->add_fileFromString("Este es otro archivo comprimido", "prueba2.txt");
  4. $zip->add_file("/images/foto.jpg","foto.jpg"); //También es posible agregar archivos
  5. $zip->add_dir("mas_images");//agregar directorio
  6. $zip->add_file("/images/foto2.jpg","mas_images/foto.jpg");
  7. $zip->add_file("/images/foto3.jpg","mas_images/foto2.jpg");
  8. header("Content-type: application/force-download");
  9. header("Content-Transfer-Encoding: Binary");
  10. header("Content-length: ".strlen($zip->file()));
  11. header("Content-Type: application/octet-stream");
  12. header("Content-Disposition: attachment; filename=\"All-Leagues-{$format}.zip\"");
  13. echo $zip->file();
  14. ?>

Este ejemplo guarda el archivo directamente en el disco duro del servidor:

  1. $zip = new zip();
  2. $zip->add_fileFromString("Esto es una prueba\n Estoy probando hola 1, 2, 3 probando... ", "prueba.txt");
  3. $zip->add_fileFromString("Este es otro archivo comprimido", "prueba2.txt");
  4. $fileName = substr(md5(rand()),0,5)."-archivo.zip";
  5. $fd = fopen ($fileName, "wb");
  6. $out = fwrite ($fd, $zip->file());
  7. fclose ($fd);
  8. ?>


0 comentarios:

Publicar un comentario

 
Top