before_action :why I need .pdf?
現階段接了一項新任務,為專案做出 pdf 檔案
專案在如火如荼地進行著,實作將 html 轉成 pdf 格式!
原本運用的是 wicked_pdf, 後來又使用了 jspdf + html2canvas 來製作這項功能,
就想著順道來記錄一下,每一階段在運行的狀況!
# Step by step to generate .pdf - version 1
安裝 wicked_pdf
與 wkhtmltopdf-binary
依照 wicked_pdf README.md 說明,
需要先將 wicked_pdf
與 wkhtmltopdf-binary
載入:
1 | gem 'wicked_pdf' |
實際上 wicked_pdf 是使用 wkhtmltopdf 這個 command line tools 來把html轉成pdf!
為 controller 建立轉檔方法
以自己想要哪一個頁面轉為 pdf 來做方法設定,這裡是以 ResumesController 的 show 來做:
1 | class ResumesController < ApplicationController |
要注意的是,如果是用 Rails 7 的話,必須將 format.pdf 的寫法轉換成:
1 | format.pdf do |
如果是照著 README.md 的方法寫會一直噴出 Template is missing 錯誤!
在 show.html.erb 設定連結到 .pdf 頁面上:
1 | <%= link_to 'PDF this profile', resume_path(@resume, format: :pdf) %> |
除此之外,讓 pdf 可以讀取樣式,因為 wicked_pdf 是以 wkhtmltopdf-binary 二進制在 Rails 應用程序之外運行,所以在 layout 上必須設定以下 wicked_pdf 相關連結:
1 |
|
以上是 wicked_pdf 需要注意的主要重點,
剩下的可以在 GitHub 的 README.md 上做更仔細的設定!
接著要來介紹最終決定的套件!jspdf
# Step by step to generate .pdf - version 2
因為專案上是以 Rails 7 進行,在引入 javascript 套件時,我使用 importmap 的方式引入!
當你在使用 jspdf 時,本身套件就涵蓋 html2canvas,可以依照 README 文件去做設定!
我主要分享在運用這個套件所遇到的問題!
Sovling Problems
- 實作將履歷在網頁上運用截圖的方式,但在使用 html2canvas 時,
一直出現Uncaught (in promise) DOMException: Failed to execute 'toDataURL' on 'HTMLCanvasElement': Tainted canvases may not be exported.
錯誤,因為我在專案上傳圖片時,是儲存在 AWS S3 bucket 裡,在訪問 AWS S3 上的圖片上會有 CORS 的設置問題,已確定我在 AWS S3 上的 CORS 設置,並且還依照一下連結的方式設置,還是有同樣的錯誤,當時決定冷靜一天…
Handling CORS with html2Canvas and AWS S3 Images: A Comprehensive Guide
終於,在隔天!我找到了最終解法:將圖片轉換為 Base64 編碼!!!
(困擾我整整兩天的 pdf 終於有結果了!)
在 Rails 中,我透過 Helper 來優化 view 上面的程式碼,其中最重要的部分是將圖片轉為 Base64,一開始的圖片路徑都是寫絕對路徑的方式導向 AWS S3 儲存庫,就是因為這點有 CORS 的問題,因此,當下先從 stackoverflow 去尋找與我有著相同錯誤的討論,當時一直卡在設置 CORS 的規格上,後續發現那裡不是主要的問題,而是我應該要改成相對路徑或者 Base64 的編碼,這樣在取用上才不會有問題。
1 | module ResumesHelper |
參考資料:
➫ [Rails]如何使用 wicked pdf 生成 pdf
➫ jspdf+html2canvas
➫ 跨來源資源共用(CORS)
➫ CORS 是什麼? 為什麼要有 CORS?