Blog sobre desarrollo de software

Ver más

Post etiquetado con pdfkit

Revisitando PDFKit

Hace un par de meses comente en el post “PDFKit irreverencia y monkey patches” que estaba haciendo uso de PDFKit para generar formatos llenos a partir de la información que un usuario captura en una forma web.

En esa ocasión también mencione que PDFKit no estaba funcionando de manera correcta para mi y por mis búsquedas en Google, al parecer había mas persona que sufrían del mismo problema. Mencione también que había encontrado al solución a mi problema modificando el método to_pdf de la clase PDFKit, donde modifique la forma en como desde Ruby se estaba ejecutando un subproceso, el cual recibía a través de un pipe la entrada de datos y a través de otro pipe, este subproceso nos generaba un resultado.


Este subproceso es la llamada a wkhtmltopdf, el cual es una herramienta de linea de comando, que puede recibir a través de un pipe de entrada código de HTML, para posteriormente convertir ese código a un archivo PDF, la solución fue modificar el código de la función to_pdf para hacer uso de IO.popen.

En ese momento que hice mi cambio no envie parche a PDFKit lo deje en la lista de espera, y de momento hice un “Monkey Patch” de la libreria en mi aplicación de Rails. Has hace unos dias me acorde del parche y me dispuse a enviarlo, pero revisando los commits en PDFKit me di cuenta que alguien mas ya había enviado el parche con mi misma solución. Así que solo procedi a quitar mi “Monkey Patch” y actualizar la libreria a la version v0.5.0.

Finalmente ya a punto de hacer el deploy de la aplicación a Heroku, surgió la situación de como instalar la libreria wkhtmltopdf en el slug de Heroku. La solución es facil y la encontre en este post.

Basicamente lo que tenemos que hacer es descargar wkhtmltopdf compilado de forma estática para la plataforma Linux AMD64, ponemos el ejecutable en un directorio bin dentro de nuestro RAILS_ROOT y creamos un archivo de inicialización donde le indiquemos a PDFKit que el wkhtmltopdf esta en nuestro directorio bin, el archivo de inicialización puede ser config/initializers/pdftokit.rb:

PDFKit.configure do |config|

config.wkhtmltopdf = Rails.root.join(‘bin’, ‘wkhtmltopdf-amd64’).to_s if Rails.env.production?

end

Listo con esto podemos usar PDFKit en Heroku.


PDFKit irreverencia y los monkey patches

Hace unos días, para un proyecto con un cliente, tuve la necesidad de poder generar archivos PDF a partir de que sus usuarios llenaran ciertos datos de una forma, para posteriormente y de forma automática, llenar un formato y permitirles descargarlo en PDF.

Para Ruby, hay varias opciones de hacer eso, por ejemplo esta Prawn, Wicked PDF y PDFKit, siendo las dos ultimas las mas sencillas de usar y que se ajustaban a mi necesidad, ya que con PDFkit, por ejemplo, puedo generar una vista en Rails y a partir de la vista generar mi PDF, por ejemplo de la siguiente forma:


Lo mejor de todo, es que PDFKit hace uso del motor de “rendereo” Webkit, el mismo de Chrome y Safari lo cual es un plus para crear formatos vistosos con html; esto es con la ayuda de wkhtmltopdf.

Hasta aquí todo parece esta muy bien, mi problema comenzó a tratar de generar mi primer formato, PDFKit me generaba un error, relacionado a que la llamada a wkhtmltopdf fallaba.

Todo parecia estar bien, pero no podía hacer que PDFKit me funcionara. Así, que siendo PDFKit OSS procedí a revisar el código fuente y ver si podía descubrir el problema. Navegando en el código llegue al culpable. El metodo to_pdf siempre me generaba error sin importar nada.


Resulta que to_pdf abre 2 pipes, un stdout y un stdin, uno para poder ejecutar el comando wkhtmltopdf con las opciones para la generación del pdf y el html a usar, otro para poder leer el resultado - que es el binario del pdf generado -, pero resulta que la lectura siempre viene vacía, aun y cuando wkhtmltopdf si genere el pdf. Después de revisar el código, no pude ver nada obvio que estuviese mal, pero no podía hacer que funcionara.

Así que me puse a reimplementar el metodo to_pdf, pero en lugar de usar exec, lo cambie a usar popen como se muestra a continuación.


Después de la redefinición del método to_pdf, PDFKit trabajo como debe, el parche aun no lo envío al autor de PDFKit y no se si lo aceptara o no, y no quiero terminar con mi propia versión de la gema en mi sistema, así que para poder usar PDFKit con mi cambio, me decidí a crear un MonkeyPatch, creando dentro del directorio de initializers de mi aplicación de Rails el archivo pdfkit.rb, donde hago una redefinición del método to_pdf cada que se inicializa mi aplicación, dejando de esta forma la gema original intacta.

Para saber mas sobre como funciona PDFKit, les recomiendo los siguientes sitios: