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) Phần 1. Giới ...
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)
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
Vì 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
Vì 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 CSS và JS
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