Puede parecer ridículo el objeto de este artículo, pero a más de uno le interesará.
Uno de nuestros partners va a implementar en su portal móvil un buscador gestionado por JumpTap y solicitaba hace unos meses a los proveedores que trabajábamos para él que les enviásemos un archivo XML con nuestro catálogo de contenidos. El archivo XML debería estar zipeado y además disponible en una URL para poder actualizarlo periódicamente. Como resulta obvio, en un escenario normal, tendríamos que generar manualmente este archivo, algo a lo que, por supuesto, no estábamos dispuestos. Teníamos además un problema adicional. Nuestra plataforma de portales móviles es físicamente única, sólo hay una instancia en disco, con lo cual los archivos generados tendrían que tener distintos nombres para que el proveedor pudiese descargar cada uno sin sobreescribirlos cada vez que quisiera actualizarlos. Además el nombre del archivo debería ser el utilizado para la descarga, es decir, si el archivo iba a ser comprimido.zip, habria que descargar ese archivo, no llamar a un compromido.php que devolviese el zip con una cabecera:
header("Content-Disposition: attachment; filename="comprimido.zip"");
o hacer un redirect final al zip. Esto es debido a que al automatizar el proceso necesitaban descargar automáticamente el archivo. Piensa que un file_get_contents o abrir un socket para recoger el archivo no interpretará esos datos.
Primero el servidor
Hay que decirle a Apache que cuando llamen a determinados archivos ZIP de nuestro servidor se llamará a un script PHP. Podríamos hacer que la extensión .zip fuese parseada automáticamente por PHP, pero entonces ya no podríamos descargar nunca un ZIP normal. La mejor opción: mod_rewrite:
RewriteEngine on RewriteCond %{REQUEST_URI} ^(.+)catalogo_(.+).zip$ RewriteRule ^(.+)catalogo_(.+).zip /catalogo_zip.php$1
Es decir, cada vez que se llame a loqueseacatalogo_loquesea.zip, el servidor web llamará intermente al script catalogo_zip.php. En nuestro caso, los archivos estaran formados por el nombre del host desde el que se llaman, así cada host o portal tiene un archivo diferente, por ejemplo catalogo_portal1.dominio.com.zip, catalogo_portal2.dominio.com.zip, catalogo_dominio2.com.zip. El proveedor del servicio recogería los archivos desde:
- http://portal1.dominio.com/catalogo_portal1.dominio.com.zip
- http://portal2.dominio.com/catalogo_portal2.dominio.com.zip
- http://dominio2.com/catalogo_dominio2.com.zip
respectivamente, respetando las normas que hemos impuesto: distintos archivos para distintos portales.
Ahora el script
Ahora que Apache ya sabe como interpretar nuestros ZIP’s falsos, llega el momento de generar realmente los archivos. Para eso hacemos uso de las funciones ZIP de PHP que nunca había utilizado pero que me han sorprendido gratamente..
$xml="<nuestro XML generado />"; $filename="descargas/catalogo_".$_SERVER['HTTP_HOST'].".zip"; if(file_exists($filename)) unlink($filename); $zip = new ZipArchive(); $zip->open($filename, ZIPARCHIVE::CREATE); //guardamos nuestro archivo XML $zip->addFromString("catalogo_".$_SERVER['HTTP_HOST'].".xml", $xml); $zip->close(); //mostramos el zip header("Content-Type: application/zip"); header("Content-Length: ".filesize($filename)); readfile($filename); unlink($filename);
Básicamente creamos un nuevo archivo, añadimos el XML y lo lanzamos como respuesta a la solicitud HTTP. La magia es la función addFromString que nos evita tener que escribir primero el XML a un archivo auxiliar. Se podrían añadir otros archivos externos con addFile si fuese necesario.
Y eso es todo, con pocas líneas de código hemos hecho la vida un poco más sencilla.
2 comentarios en “Generando Zips bajo demanda en PHP”