+1

Sử dụng wicked_pdf nâng cao cho dự án Rails

Trong qúa trình làm việc với wicked_pdf, mình cũng gặp phải một số vấn đề và cũng đã tìm ra cách giải quyết nên trong bài viết này mình muốn chia sẻ, hi vọng nó sẽ có ích với các bạn.

Bạn có thể tham khảo bài viết Export file pdf trong Rails trước đây của mình. Bài viết đó đã trình bày khá chi tiết về cách cài đặt cũng như sử dụng gem wicked_pdf xuất ra một file pdf đơn giản trong một dự án Rails.

Debuging.

Trước tiên mình tạo một file controller test_files_controller.rb đơn giản như sau:

class TestFilesController < ApplicationController
  def export_file
    format.html { render :index }
    format.pdf do
      render pdf: 'tribeo',
             # type: 'application/pdf',
             # disposition: 'attachment',
             encoding: 'UTF-8',
             layout: 'pdf.html.erb',
             template: 'test_files/tribeo_template.html.erb',
             page_size: 'A4'
    end
  end
end

Như code bên trên thì bạn phải có thêm layout, template để xuất file pdf (bạn có thể xem bài biết mình có dẫn link bên trên để xem chi tiết hơn nhé).

Trong ví dụ này chỉ xuất ra một file pdf có chứa một bảng ngắn, và mình cũng comment 2 key typedisposition lại để render kết quả ra html show lên trình duyệt như sau (url http://localhost:3000/test_files/export_file/tribeo.pdf):

Làm thế này, chúng ta sẽ không thể nào inspect chi tiết phần nội dung bên trong cho file pdf, do đó khi bạn phải chỉnh sửa hiển thị cho file thì rất khó khăn (mình đã từng gặp rất nhiều khó khăn cho vấn đề này 😄). Rất may là wicked_pdf có cung cấp cho chúng ta một cách khá đơn giản để giải quyết vấn đề đó.

Để tiến hành debug cho file pdf, chúng ta cần thực hiện 2 bước sau:

  • Thêm key show_as_html: params.key?('debug') vào trong render.

  • Phải sử dụng method GET cho hành động export_pdf ở trên thì mới có thể nhảy vào debug file pdf được.

Như ví dụ mình đửa ở trên, chúng ta sẽ phải thay đổi form, routes một chút để sử dụng hàm export_file với phương thức GET chứ không phải POST; thêm key show_as_html vào. Sau khi ra được kết quả file pdf trên trình duyệt, thêm tham số debug vào sau url đó như sau http://localhost:3000/test_files/export_file/tribeo.pdf?debug. Hãy cùng xem kết quả:

Như vậy, ta có thể inspect trang pdf đó ra để chỉnh sửa y hệt như là chỉnh sửa một trang html vậy.

* Lưu ý nhỏ là khi để ở chế độ debug này thì wicked_pdf sẽ phân biệt được xuống trang đâu nhé, việc hiển thị ảnh cũng thay đổi đổi chút, bạn có thể xem chi tiết hơn ở Github.

Đính kèm file pdf vào email.

Mình sẽ không đi chi tiết cách làm để gửi email trong Rails, mặc định là các bạn đã biết rồi nhé 😄. Ở đây mình chỉ giới thiệu cách dùng wicked_pdf để đính thêm file pdf vào một email mà thôi.

Mình tạo một file mailers/test_mailer.rb như sau:

class TestMailer < ApplicationMailer
  def pdf_file_attach
    attachments['tribeo.pdf'] = WickedPdf.new.pdf_from_string(
      render_to_string(
        pdf: 'tribeo'
      ),
      # bạn có thể thêm vào mảng các options của wicked_pdf
    )
    mail(
      to: 'vo.tai.tri@framgia.com',
      subject: 'Your PDF file is attached'
    )
  end
end

Với method pdf_file_attach trên, bạn sẽ cần thêm 2 file view pdf_file_attach.html.erbpdf_file_attach.text.erb trong thư mục views/test_mailer/ để làm nội dung cho email đó. Đơn giản như sau:

Dear tribeo. This is attached file for you.

Với code như trên thì ta hãy thử vào console gửi một email đi để xem kết quả ra sao nhé.

[1] pry(main)> TestMailer.pdf_file_attach.deliver_now
  Rendered manager_mailer/pdf_file_attach.html.erb within layouts/mailer (1.8ms)
"***************[\"/usr/local/bin/wkhtmltopdf\", \"-q\", \"file:////var/folders/51/gscjbprn76d72xg0bnqthkn4m5z5k5/T/wicked_pdf20180123-3709-1eakhtz.html\", \"/var/folders/51/gscjbprn76d72xg0bnqthkn4m5z5k5/T/wicked_pdf_generated_file20180123-3709-1a6eaxj.pdf\"]***************"
  Rendered manager_mailer/pdf_file_attach.html.erb within layouts/mailer (0.1ms)
  Rendered manager_mailer/pdf_file_attach.text.erb within layouts/mailer (0.4ms)

TestMailer#pdf_file_attach: processed outbound mail in 1560.8ms

Sent mail to vo.tai.tri@framgia.com (1407.9ms)
Date: Tue, 23 Jan 2018 11:10:44 +0700
From: votaitri.hust@gmail.com
To: vo.tai.tri@framgia.com
Message-ID: <5a66b5c4ca316_e7d3fe526463bec22862@framgias-Mac-mini.local.mail>
Subject: Your PDF file is attached
Mime-Version: 1.0
Content-Type: multipart/mixed;
 boundary="--==_mimepart_5a66b5c4c822d_e7d3fe526463bec22764";
 charset=UTF-8
Content-Transfer-Encoding: 7bit
...

=> #<Mail::Message:70253496667740, Multipart: true, Headers: <Date: Tue, 23 Jan 2018 11:10:44 +0700>, <From: votaitri.hust@gmail.com>, <To: vo.tai.tri@framgia.com>, <Message-ID: <5a66b5c4ca316_e7d3fe526463bec22862@framgias-Mac-mini.local.mail>>, <Subject: Your PDF file is attached>, <Mime-Version: 1.0>, <Content-Type: multipart/mixed; boundary="--==_mimepart_5a66b5c4c822d_e7d3fe526463bec22764"; charset=UTF-8>, <Content-Transfer-Encoding: 7bit>>

Hộp thư của mình đã có một email mới được gửi đến như sau:

File pdf mình đính kèm ở đây mới chỉ là một file rỗng mà thôi, bạn hãy cho thêm nội dung vào bên trong render_to_string() nhé.


Cám ơn bạn đã đọc bài viết này và hi vọng nó sẽ có ích với bạn.

tribeo


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí