lunes, 15 de abril de 2013

Generando una pantallazo

Tenemos que resolver la siguiente feature en una aplicación Ruby on Rails 3.2: es necesario pintar una tabla HTML normalita y poder descargarla como imagen. La solución o tienen ningún misterio, pero sí puede ser conveniente revisar un par de trucos que nos facilitarán la vida.

Primero, preparamos el controller. Necesitamos la gema IMGKit y generar la el HTML que vamos a convertir en imagen a través de un layout semivacío.

require 'imgkit'
...

kit = IMGKit.new(render_to_string :index, formats: [:html], layout: 'html2img')
respond_to do |format|
  format.png { send_data(kit.to_img(:png), :type => "image/png", :disposition => 'attachment', filename: 'table.png') }
end


Esto por sí sólo es posible que funcione en un entorno previamente configurado, especialmente si es un Lynux. En windows, por lo general hacen falta dos cosillas:
  1. Instalar wkhtmltoimage, que viene con wkhtmltopdf. Lo podéis encontrar aquí.
  2. Configurar la ruta al ejecutable que hará la conversión, por ejemplo en /config/initializers/imgkit.rb

    config.wkhtmltoimage = 'C:\Program Files (x86)\wkhtmltopdf\wkhtmltoimage.exe'
Con esto tendremos una imagen. Pero... por desgracia el ejecutables no se va a enterar muy bien de dónde buscar las css. La solución más rápida es pasársela explícitamente en el controlador, ya sea leyendo un fichero o, si es poca cosa, mediante un string.

css = StringIO.new("html,body{height:100%; font-family :Arial ,sans-serif; font-size: 13px; line-height: 14px}...")
kit.stylesheets << css


Et voilà! Listo para descargar. ¡Salud y rocanrol!

Bola extra!
Si en la generación de la imagen os aparecen tres caracteres no-cristianos como ï»¿ , no os asustéis. Estos caracteres son el Byte Order Mark de la codificación en UTF-8 de algún fichero. Revisad los layouts y las vistas implicadas y salvad todos sin ese BOM.

Time out - let's get something clear
I speak - more truth than you want to hear
Scapegoat - to cover up your fear... you can't bring me
You ain't - never seen so much might
Fight for - what I know is right
What up - you got yourself a fight... you can't bring me
Stand up - we'll all sing along
Together - aint nothing as strong
Won't quit - we ain't in the wrong... you can't bring me

You - can't - bring - me - down!