Export pdf in rails app
Bài đăng này đã không được cập nhật trong 3 năm
Các file pdf hiện nay là một format được nhiều người ưu chuộng vì tính thuận tiện trong việc trao đổi thông tin. Tính thuận tiện được thể hiện: người đọc không thể thay đổi nội dung của file, phần mềm đọc pdf không phải phụ thuộc vào các phiên bản, hay phông chữ giống như office. Chính vì những lý do trên mình sẽ viết một ví dụ về kĩ thuật export file pdf trong rails app. Hy vọng bạn sẽ thấy bài viết có ích
Trong bài viết này mình có sử dụng gem wicked pdf. Đây là link của của gem: https://github.com/mileszs/wicked_pdf.
1. Add gem wicked pdf in rails app
Thêm vào Gemfile dòng dưới đấy, sau đó gõ bundle install:
gem 'wicked_pdf'
Sau đó tiếp tục gõ:
rails generate wicked_pdf
Sau khi gõ lệnh trên file config/initializers/wicked_pdf.rb sẽ tự động được sinh ra bởi rails app. Đây là file config chung cho wicked pdf.
Thêm dòng sau vào trong thư mục config/initializers/mime_types.rb với các bản rails cũ
Mime::Type.register "application/pdf", :pdf
Tuy nhiên đến đấy vẫn chưa config xong bạn còn phải thêm gem:
gem 'wkhtmltopdf-binary'
Gõ bundle install (Để hiểu rõ hơn bạn có thể vào đây để tham khảo: http://wkhtmltopdf.org/). Trong bài viết này mình sẽ thực hiện export profile user ra filf pdf.
2. Basic Usage
Tạo một controller riêng để xử lý việc export file pdf. Giả sử mình sẽ tạo controller có tên "pdf"
rails g controller Pdfs
Trong controller pdf có một phương thức show để xử lý việc export.
class PdfsController < ApplicationController
def show
@user = User.find_by id: params[:user_id]
respond_to do |format|
format.html
format.pdf do
render pdf: "#{@user.name}_#{Time.now.strftime("%Y-%m-%d %H:%M:%S")}",
template: "pdfs/show.html.erb",
disposition: "attachment",
layout: "pdf",
orientation: "Landscape",
encoding: "UTF-8"
end
end
end
end
Mình sẽ giải thích một số thuộc tính mình sử dụng ở trên: render
-
pdf: Tên của file sau khi generate.
-
template: Wicked_pdf sẽ render từ html sang pdf (nói cách khác phần view mà hiển thị trên trang web sẽ được chuyển thành file pdf).
-
disposition: file pdf sau khi tạo sẽ được tự động download về máy
-
layout: wicked_pdf sẽ tự động tìm kiếm trong thư mục layouts của view file có tên pdf.html.erb (app/views/layouts/). Thay vì sử dụng layout application.html.erb wicked_pdf sẽ sử dụng layout pdf mà mình tạo được(cái này quan trọng nhé mình sẽ giải thích sau)
-
Đối với các phần còn lại các bạn có thể tham khảo ngày tại trang trủ của gem còn rất nhiều thuộc tính khác có thể sử dụng, trên đây là một số tính năng cơ bản.
3. Tip and trick
Add css to view in pdf
Với các bước như trên thì bạn đã có một tính năng export ra file pdf tuy nhiên như thể là chưa đủ vì sau khi export: css của view sẽ không có. Là do wkhtmltopdf binary chạy ở ngoài luồng của ứng dụng rails, chính vì thể wicked pdf sẽ không thể hiểu cơ chế asset pipeline của rails cũng như applications layout sẽ không hoạt động.
Do đó để nếu bạn muốn sử dụng css hoặc ảnh thì bạn phải sử dụng template khác đó là lý do tại sao ở phần basic useage mình có thêm thuộc tính là layout: "pdf". Wicked cung cấp các phương thức để chỉ ra file css, image, javascript nào sẽ được sử dụng . Ví dụ trong pdf layout của mình sư sau:
<!DOCTYPE html>
<html>
<head>
<title><%= full_title yield :title %></title>
<%= wicked_pdf_stylesheet_link_tag "admin/pdf" %>
<%= wicked_pdf_stylesheet_link_tag "admin/users" %>
<%= csrf_meta_tags %>
<meta name="turbolinks-cache-control" content="no-cache">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css">
</head>
<body>
<%= yield %>
</body>
</html>
Và một số các helper khác như sau: wicked_pdf_image_tag (sử dụng trong view để thay cho image_tag), wicked_pdf_javascript_include_tag
Page Breaks
Việc render từ html sang pdf không thể đảm bảo wicked pdf sẽ hiển thị đúng như ý muốn do độ dài của các phần là khác nhau. Do đó wicked cung cấp css để hạn chế tình trạng ngắt dòng không đúng
#users{
.alwaysbreak { page-break-before: always; }
.nobreak:before { clear:both; }
.nobreak { page-break-inside: avoid; }
}
Wicked_pdf with bootstrap
Như mình đã nói giới thiệu ở trên wkhtmltopdf binary sẽ không hiểu cơ chế asset pipeline của rails do đó wicked_pdf không hiểu cơ chế col sm/md/lg của bootstrap. Để giải quyết vấn đề mình sẽ tạo file pdf.css.scss và sử dụng đường dẫn tuyệt đối của wicked_pdf:
@import "bootstrap-sprockets";
@import "bootstrap";
@import "mixin";
@import "flexslider";
@include make-grid(sm);
@include make-grid(md);
@include make-grid(lg);
#users {
.alwaysbreak {
page-break-before: always;
}
.nobreak:before {
clear:both;
}
.nobreak {
page-break-inside: avoid;
}
}
Bài viết đến đây là kết thúc. Xin chân thành cảm ơn.
Tham khảo
Bài viết có sự tham khảo từ blog : https://github.com/mileszs/wicked_pdf
All rights reserved