2011-01-17 15 views
8

Una de las responsabilidades de mi aplicación Rails es crear y servir xmls firmados. Cualquier xml firmado, una vez creado, nunca cambia. Así que guardo cada xml en la carpeta public y redirijo el cliente de manera apropiada para evitar el procesamiento innecesario desde el controlador.Servicio de archivos zip dinámicos a través de Apache

Ahora quiero una nueva característica: cada xml está asociado con una fecha, y me gustaría implementar la capacidad de servir un archivo comprimido que contenga cada xml cuya fecha se encuentre en un período especificado por el cliente. Sin embargo, el período no puede limitarse a menos de un mes para que la función sea útil, y esto implica que algunos archivos comprimidos que se sirven serán tan grandes como 50M.

Mi aplicación se implementa como un módulo de Pasajeros de Apache. Por lo tanto, es totalmente inaceptable servir el archivo con send_data, ya que el cliente tendrá que esperar a que se genere todo el archivo comprimido antes de que comience la descarga. Aunque tengo una idea sobre cómo implementar la función en Rails para que se produzca el archivo comprimido mientras recibo el servicio, creo que mi servidor escasea en recursos una vez que se asignan algunos largos procesos Ruby/Passenger para servir archivos zip grandes.

He leído acerca de a better solution para servir archivos estáticos a través de Apache, pero no los dinámicos.

Entonces, ¿cuál es la solución al problema? ¿Necesito algo así como un controlador de Apache personalizado? ¿Cómo informo a Apache, desde mi aplicación, cómo manejar la solicitud, comprimir los archivos y transmitir el resultado de forma simultánea?

+0

El índice formato de archivo ZIP se encuentra al final del archivo. También eché un vistazo rápidamente a través de RFC 2616 (HTTP 1.1) y la respuesta de longitud variable como esa probablemente funciona, aunque generalmente debe anunciarse la duración del contenido. Técnicamente esto debería ser posible por lo que puedo ver. – erloewe

+0

No existe un problema de HTTP al no saber la longitud por adelantado, para esto sirve la codificación de transferencia fragmentada. Puede escribir bytes que se parecen a un archivo zip en cualquier idioma, solo asegúrese de enjuagar su salida periódicamente. – covener

Respuesta

3

Compruebe hacia fuera mi módulo mod_zip para Nginx:

http://wiki.nginx.org/NgxZip

Usted puede tener un script backend decir Nginx qué ubicaciones URL para incluir en el archivo, y Nginx transmitirá dinámicamente un archivo ZIP en el cliente que contiene esos archivos. El módulo aprovecha el código proxy de subproceso único de Nginx y es extremadamente liviano.

El módulo se lanzó por primera vez en 2008 y es bastante maduro en este momento. Según su descripción, creo que se ajustará a sus necesidades.

0

Simplemente necesita usar cualquier API que tenga disponible para crear un archivo zip y escribirlo en la respuesta, lavando el resultado periódicamente. Si esto sirve grandes archivos zip, o se solicitará con frecuencia, considere ejecutarlo en un proceso separado con un alto valor de ionice/baja prioridad.

En el peor de los casos, podría ejecutar un zip de línea de comandos en un proceso de baja prioridad y pasar periódicamente la salida.

0

es complicado de hacer, pero he hecho una gema llamada zipline (http://github.com/fringd/zipline) que hace que las cosas funcionen para mí. Quiero actualizarlo para que admita controladores o rutas de archivos simples, en este momento se supone que está utilizando carrierwave ...

también, es probable que no pueda transmitir la respuesta con el pasajero ... Tuve que usa unicornio para hacer que la transmisión funcione correctamente ... y cierto middleware de rack incluso puede arruinarlo (respuesta de llamada).to_s la rompe)

si alguien todavía necesita esto me molesta en la página de GitHub

Cuestiones relacionadas