DEV Community

Cover image for Generate PDF with Ferrum (headless Chrome API)
Yaroslav Shmarov
Yaroslav Shmarov

Posted on • Originally published at blog.corsego.com on

Generate PDF with Ferrum (headless Chrome API)

Thanks to URLBOX for sponsoring this blogpost! Convert URL to PNG/PDF with UrlBox screenshot API. Urlbox also helps to block Ads & Popups, Bypass Captchas, Auto-Accept Cookies.


Usually I would use an HTML-to-PDF library to to generate and display a PDF.

An absolutely different , alternative way to view or download a page as PDF would be via a headless browser API.

Gem Ferrum lets you open a headless chrome browser and perform different actions (click link, take screenshot, open as PDF, etc.)

Why not use Ferrum to open or save a file as PDF?

Here’s how it could work:

Example of an HTML page ⤵️

Ferrum HTML page

Clicking the “View as PDF” link would open a link as PDF ⤵️

Ferrum page turned into PDF

Install and use Gem Ferrum

Install the gem:

# Gemfile gem "ferrum" 
Enter fullscreen mode Exit fullscreen mode

Add a route:

# config/routes.rb get 'home/index' 
Enter fullscreen mode Exit fullscreen mode

Add an HTML page.

You can add a link_to render the page as PDF.

Notice I add a class .no-print, so that the link does not get displayed in print media type.

<!-- app/views/home/index.html.erb --> <h1>Home#index</h1> <p>Find me in app/views/home/index.html.erb</p> <div class="no-print"> <%= link_to "View as PDF", home_index_path(format: :pdf) %> </div> 
Enter fullscreen mode Exit fullscreen mode

Add .no-print CSS class to elements that should not be printable:

/* app/assets/stylesheets/application.css */ @media print { .no-print { display: none !important; } } /* other css classes you might want to add */ @media print { body { -webkit-print-color-adjust: exact; background: #fff; background-color: #fff; float: none; display: block; } .no_margin { padding-left: 0px !important; } .no-print { display: none !important; } .printer-preview-content, .printer-preview-content_landscape { max-width: 100% !important; width: 100% !important; height: auto !important; padding: 0 !important; margin: 0 !important; } .cover_div { display: table; } } 
Enter fullscreen mode Exit fullscreen mode

Finally, use Ferrum to navigate to an internal or external URL and display it as PDF:

# app/controllers/home_controller.rb class HomeController < ApplicationController def index respond_to do |format| format.html format.pdf do handle_pdf_format end end end private def handle_pdf_format filename = controller_name tmp = Tempfile.new("pdf-chrome-#{filename}") browser = Ferrum::Browser.new # browser.go_to("http://localhost:3000/home/index") browser.go_to(home_index_url) # browser.go_to("https://google.com") # click_on_text "Accept all" # browser.at_css(".QS5gu.sy4vM").click sleep(0.3) browser.pdf( path: tmp.path, format: "A4".to_sym, landscape: false, # margin: {top: 36, right: 36, bottom: 36, left: 36}, # preferCSSPageSize: true, # printBackground: true ) browser.quit pdf_data = File.read(tmp.path) pdf_filename = "#{filename}.pdf" send_data(pdf_data, filename: pdf_filename, type: "application/pdf", disposition: "inline") ensure tmp.close tmp.unlink end end 
Enter fullscreen mode Exit fullscreen mode

It works well for publicly accessible URLs, however it is not so straightforwar for links that require current_user authentication. I’ve asked a question here https://github.com/rubycdp/ferrum/issues/423 and am hoping for an easy enough solution 🤠

Top comments (0)