-1

Export file pdf trong Rails

Cũng khá lâu trước đây mình có bài viết về việc sử dụng gem RubyXL để export file excel, hôm nay mình xin giới thiệu đến các bạn cách sử dụng gem Wicked_pdf để export ra file pdf (ngoài ra thì bạn có thể tìm hiểu thêm một gem khác cũng khá hay trong trường hợp này là PDFKkit)

banner.jpg

Phần 1. Giới thiệu

Đơn giản, bạn có thể hiểu wicked_pfd là một gem sử dụng wkhtmltopdf để xuất nội dung ra một file pdf từ HTML

Gem wicked_pfd tương thích với

  • Ruby phiên bản 1.8.7 đến 2.3.
  • Rails 2 đến 5.0.

Phần 2. Cài đặt

wicked_pfd được đóng gói cho wkhtmltopdf, nên trước tiên chúng ta cần phải cài đặt wkhtmltopdf cho hệ thống. Nếu dùng Ubuntu thì bạn có thể tiến hành cài đặt theo hướng dẫn ở đây

Thêm gem vào Gemfile và tiến hành bundle install

gem "wicked_pdf"
gem "wkhtmltopdf-binary"

Generate wicked_pdf

rails generate wicked_pdf

Câu lệnh trên sẽ tự động sinh ra cho bạn file cấu hình : config/initializers/wicked_pdf.rb. Và nếu việc thực thi wkhtmltopdf không nằm trên đường dẫn server của bạn thì bạn sẽ phải cấu hình thêm cho file này như sau

WickedPdf.config = {
  exe_path: "/usr/local/bin/wkhtmltopdf"
}

Với một số phiên bản Rails cũ thì cần phải cấu hình thêm trong file config/initializers/mime_types.rb

Mime::Type.register "application/pdf", :pdf

Nếu như bạn vẫn cấu hình như trên với những phiên bản Rails mới thì hệ thống của bạn vẫn có thể chạy thông mà không bị chết. Tuy nhiên sẽ có một số warning của hệ thống tương tự như sau

warning: already initialized constant PDF
warning: previous definition of PDF was here

Để sử dụng wicked_pdf cho cả dự án của mình thì bạn cần khai báo trong file application.rb (với Rails 3) hoặc environment.rb (với Rails 2)

require 'wicked_pdf'
config.middleware.use WickedPdf::Middleware

Phần 3. Sử dụng

wkhtmltopdf-binary được chạy bên ngoài ứng dụng Rails, nên chúng ta cần phải chỉnh sửa lại layout để cung cấp cho hệ thống đường dẫn tuyệt đối đến các file javascript, css hoặc là file ảnh cần thiết. Có 2 cách để làm việc này

Nếu dùng các helpers có sẵn thì ta có layout tương tự như sau

<!doctype html>
<html>
  <head>
    <meta charset='utf-8' />
    <%= wicked_pdf_stylesheet_link_tag "pdf" -%>
    <%= wicked_pdf_javascript_include_tag "number_pages" %>
  </head>
  <body onload='number_pages'>
    <div id="header">
      <%= wicked_pdf_image_tag "mysite.jpg" %>
    </div>
    <div id="content">
      <%= yield %>
    </div>
  </body>
</html>

Sử dụng helper như trên với asset pipeline sẽ gây ra lỗi và bạn sẽ không thể nạp các CSS, JS từ bên ngoài. Cho nên có thể bạn sẽ phải sử dụng wicked_pdf_asset_base64 ở đây. Điều này tùy thuộc vào hề thống của bạn. Code cũng tương tự như trên, chỉ khác ở các helper

stylesheet_link_tag wicked_pdf_asset_base64("pdf")

javascript_include_tag wicked_pdf_asset_base64("number_pages")

image_tag wicked_pdf_asset_base64("mysite.jpg")

Khi khai báo layout thế này thì wicked_pdf sẽ thấy file assets/stylesheets/pdf.css, assets/javascripts/number_pages.js,... trong hệ thống của bạn để nạp vào các hàm JS hay là style cho trang pdf

Hoặc là bạn có thể đi thẳng đến một CDN (Content Delivery Network) cho những thư viện phổ biến

<!doctype html>
    <html>
      <head>
        <%= javascript_include_tag "http://code.jquery.com/jquery-1.10.0.min.js" %>
        <%= javascript_include_tag "http://code.jquery.com/ui/1.10.3/jquery-ui.min.js" %>

Nếu bạn tiến hành deploy code lên một số server như Heroku thì bạn sẽ cần config thêm trong config/initializes/assets.rb để hệ thống có thể tìm thấy file CSSJS

config.assets.precompile += ['pdf.css', 'pdf.js', ...etc...]

Định dạng cho file pdf của chúng ta

respond_to do |format|
  format.html
  format.pdf do
    render
      # define options here
  end
end

Có rất nhiều thuộc tính bạn có thể thiết lập cho file. Xin liệt kê ra một số thuộc tính mình cho rằng là cơ bản nhất

  • pdf : Tên file xuất ra.
  • type ("application/pdf") và disposition ("attachment") : Cho hệ thống biết là ta sẽ tải xuống một file (không có thì nó sẽ chỉ view ngay trên browser như một web bình thường).
  • layout : Chỉ ra file layout (dẫn đến chính cái layout đã định nghĩa ở trên).
  • template : Chỉ ra file template - nơi ta quy định tất cả nội dung của file tải xuống. Bạn code template giống hoàn toàn với việc code view.
  • locals : Là một hash chứa những variable cần thiết bạn muốn cho vào nội dung file.

Ngoài ra bạn cũng có thể khai báo các thuộc tính như header, footer; nhưng mình thích để phần này trong layout hơn 😄

Để xuống trang, bạn có thể sử dụng một trong các cách dưới đâu ở bất kỳ chỗ nào trong file của bạn

<p style="page-break-before:always;"></p>
<p style="page-break-after:always;"></p>
<p style="page-break-inside: avoid;"></p>

Để đánh số trang thì đơn giản bạn chỉ cần thêm thuộc tính header hoặc footer (với các vị trí left, center, right)

footer: { center: '[page]' }

Xong, như vậy là bạn đã có đầy đủ những kiến thức cơ bản nhất về wicked_pdf cũng như cách sử dụng gem này để xuất nội dung ra file pdf. Mình sẽ sớm làm một demo đơn giản cho bài viết này

Cám ơn các bạn đã theo dõi bài viết.


Tham khảo


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.