如何從您的 Web 應用程序創建 PDF
已發表: 2022-03-10許多 Web 應用程序要求用戶能夠下載 PDF 格式的內容。 對於應用程序(例如電子商務商店),這些 PDF 必須使用動態數據創建,並且用戶可以立即使用。
在本文中,我將探討直接從 Web 應用程序動態生成 PDF 的方法。 它不是一個完整的工具列表,但我的目標是展示不同的方法。 如果您有最喜歡的工具或您自己的任何經驗要分享,請將它們添加到下面的評論中。
從 HTML 和 CSS 開始
我們的 Web 應用程序可能已經在使用將添加到 PDF 中的信息創建 HTML 文檔。 如果是發票,用戶可以在線查看信息,然後單擊下載 PDF 以供記錄。 您可能正在創建裝箱單; 再一次,信息已經保存在系統中。 您想以一種很好的方式對其進行格式化以供下載和打印。 因此,一個好的起點是考慮是否可以使用 HTML 和 CSS 來生成 PDF 版本。
CSS 確實有處理打印 CSS 的規範,這就是 Paged Media 模塊。 我在我的文章“使用 CSS 進行印刷設計”中對此規范進行了概述,許多圖書出版商都使用 CSS 來進行所有的印刷輸出。 所以,既然 CSS 本身就有印刷材料的規範,那我們應該可以用嗎?
用戶生成 PDF 的最簡單方法是通過他們的瀏覽器。 通過選擇打印到 PDF 而不是打印機,將生成 PDF。 可悲的是,這個 PDF 通常並不完全令人滿意! 首先,當您從網頁打印某些內容時,它會自動添加頁眉和頁腳。 它還將根據您的打印樣式表進行格式化——假設您有一個。
我們在這裡遇到的問題是瀏覽器對分片規範的支持很差; 這可能意味著您的網頁內容以不尋常的方式中斷。 正如我在研究我的文章“Breaking Boxes With CSS Fragmentation”時發現的那樣,對碎片的支持是不完整的。 這意味著您可能無法防止內容的次優中斷,將標題作為頁面上的最後一項,等等。
此外,我們無法控制頁邊距框中的內容,例如在每頁添加我們選擇的頁眉或頁碼以顯示複雜發票有多少頁。 這些東西是 Paged Media 規範的一部分,但尚未在任何瀏覽器中實現。
我的文章“2018 年打印樣式表狀態指南”在瀏覽器對使用打印樣式表直接從瀏覽器進行打印的支持類型方面仍然是準確的。
使用瀏覽器渲染引擎打印
有多種方法可以使用瀏覽器渲染引擎打印到 PDF,而無需通過瀏覽器中的打印菜單,並以頁眉和頁腳結束,就像您打印了文檔一樣。 響應我的推文的最受歡迎的選項是 wkhtmltopdf,以及使用無頭 Chrome 和 Puppeteer 進行打印。
wkhtmltopdf
在 Twitter 上多次提到的解決方案是一個名為 wkhtmltopdf 的命令行工具。 該工具採用 HTML 文件或多個文件以及樣式表並將它們轉換為 PDF。 它通過使用 WebKit 渲染引擎來做到這一點。
我們使用 wkhtmltopdf。 它並不完美,儘管這可能是用戶錯誤,但對於生產應用程序來說已經足夠好了。
— Paul Cardno (@pcardno) 2019 年 2 月 15 日
因此,從本質上講,此工具與從瀏覽器打印的功能相同,但是,您不會獲得自動添加的頁眉和頁腳。 從積極的一面來看,如果您的內容有一個有效的打印樣式表,那麼它也應該使用這個工具很好地輸出到 PDF,因此一個簡單的佈局可能會很好地打印出來。
然而,不幸的是,您仍然會遇到與直接從 Web 瀏覽器打印時相同的問題,因為您仍然使用瀏覽器渲染引擎進行打印,因此缺乏對 Paged Media 規範和碎片屬性的支持。 您可以將一些標誌傳遞到 wkhtmltopdf 中,以便添加一些缺少的功能,這些功能默認情況下使用 Paged Media 規範。 然而,這確實需要在編寫好的 HTML 和 CSS 之上做一些額外的工作。
無頭鍍鉻
另一個有趣的可能性是使用 Headless Chrome 和 Puppeteer 打印到 PDF。
傀儡師。 這太神奇了。
——亞歷克斯·羅素 (@slightlylate) 2019 年 2 月 15 日
但是,您再次受到瀏覽器對分頁媒體和碎片的支持的限制。 有一些選項可以傳遞到page.pdf()
函數中。 與 wkhtmltopdf 一樣,如果有瀏覽器支持,這些添加了一些 CSS 可能提供的功能。
很可能其中一個解決方案可以滿足您的所有需求,但是,如果您發現自己正在打一場戰鬥,那麼您很可能已經達到了當前瀏覽器渲染引擎的極限,並且將需要尋找更好的解決方案。
用於分頁媒體的 JavaScript Polyfills
有一些嘗試使用 JavaScript 在瀏覽器中復制 Paged Media 規範——本質上是創建一個 Paged Media Polyfill。 這可以在使用 Puppeteer 時為您提供分頁媒體支持。 看看 paged.js 和 Vivliostyle。
是的。 對於簡單的文檔,比如課程證書,我們可以使用 Chrome,它對 @page 的支持最少。 對於其他任何事情,我們在 Chrome 中使用 PrinceXML 或 paged.js polyfill。 這是使用 paged.js 書籍的 WIP 概念證明:https://t.co/AZ9fO94PT2
— Electric Book Works (@electricbook) 2019 年 2 月 15 日
使用打印用戶代理
如果您想繼續使用 HTML 和 CSS 解決方案,那麼您需要尋找專為從 HTML 和 CSS 打印而設計的用戶代理 (UA),它具有用於從文件生成 PDF 的 API。 這些用戶代理實現了分頁媒體規範,並且對 CSS Fragmentation 屬性有更好的支持; 這將使您更好地控制輸出。 主要選擇包括:
- 王子
- 天線屋
- PDF反應器
打印 UA 將使用 CSS 格式化文檔——就像 Web 瀏覽器一樣。 與瀏覽器對 CSS 的支持一樣,您需要查看這些 UA 的文檔以了解它們支持的內容。 例如,Prince(我最熟悉的)在撰寫本文時支持 Flexbox,但不支持 CSS 網格佈局。 將頁面發送到您正在使用的工具時,通常會使用特定的樣式表進行打印。 與常規打印樣式表一樣,您在網站上使用的 CSS 並不都適用於 PDF 版本。
為這些工具創建樣式表與創建常規打印樣式表非常相似,根據顯示或隱藏的內容做出決定,可能使用不同的字體大小或顏色。 然後,您將能夠利用 Paged Media 規範中的功能,添加腳註、頁碼等。
在您的 Web 應用程序中使用這些工具時,您需要將它們安裝在您的服務器上(當然,已經購買了許可證)。 這些工具的主要問題是價格昂貴。 也就是說,鑑於您可以輕鬆地使用它們生成打印文檔,它們很可能會為自己節省開發人員的時間。
可以通過 API 使用 Prince,按文檔付費,通過名為 DocRaptor 的服務。 對於許多應用程序來說,這肯定是一個很好的起點,就好像託管您自己的應用程序會變得更具成本效益,切換的開發成本將是最小的。
WeasyPrint 是一個免費的替代品,它不像上述工具那麼全面,但可以很好地達到您需要的結果。 它沒有完全實現所有分頁媒體,但是,它實現的不僅僅是瀏覽器引擎。 絕對,一個嘗試!
其他聲稱支持從 HTML 和 CSS 轉換的工具包括 PDFCrowd,它大膽地聲稱支持 HTML5、CSS3 和 JavaScript。 但是,我無法找到有關所支持的確切內容的任何詳細信息,以及是否有任何 Paged Media 規範。 在我的推文的回復中還提到了 mPDF。
遠離 HTML 和 CSS
還有許多其他解決方案不再使用 HTML 和 CSS,而是要求您為該工具創建特定的輸出。 幾個 JavaScript 競爭者如下:
- jsPDF
- pdf製作
無頭瀏覽器 + 保存到 PDF 曾經是我的第一選擇,但對於單頁文檔以外的任何內容,總是產生低於標準的結果。 我們切換到 https://t.co/3o8Ce23F1t 獲取多頁報告,這需要付出更多的努力,但最終還是值得的!
— JimmyJoy (@jimle_uk) 2019 年 2 月 15 日
建議
除了需要您創建完全不同的打印內容表示的基於 JavaScript 的方法之外,許多這些解決方案的美妙之處在於它們是可互換的。 如果您的解決方案基於調用命令行工具,並將您的 HTML、CSS 和可能的一些 JavaScript 傳遞給該工具,那麼在工具之間切換是相當簡單的。
在撰寫本文的過程中,我還發現了一個 Python 包裝器,它可以運行許多不同的工具。 (請注意,您需要已經安裝了工具本身,但是,這可能是在示例文檔中測試各種工具的好方法。)
對於 Paged Media 和碎片化的支持,Prince、Antenna House 和 PDFReactor 將名列前茅。 作為商業產品,它們也附帶支持。 如果您有預算、要打印到 PDF 的複雜頁面,並且您的限制是開發人員的時間,那麼您很可能會發現這些是讓您的 PDF 創建工作正常的最快途徑。
但是,在許多情況下,免費工具對您很有效。 如果您的要求非常簡單,那麼 wkhtmltopdf 或基本的無頭 Chrome 和 Puppeteer 解決方案就可以解決問題。 對於許多回复我原始推文的人來說,這似乎確實有效。
但是,如果您發現自己難以獲得所需的輸出,請注意這可能是瀏覽器打印的限制,而不是您做錯了什麼。 如果您想要更多 Paged Media 支持,但又無法購買商業產品,不妨看看 WeasyPrint。
我希望這是對可用於從 Web 應用程序創建 PDF 的工具的有用匯總。 如果不出意外,這表明如果您最初的選擇效果不佳,則存在多種選擇。
請在評論中添加您自己的經驗和建議,這是我們很多人最終要處理的事情之一,分享的個人經驗可能會非常有幫助。
延伸閱讀
本文中提到的各種資源和工具的匯總,以及其他一些用於處理來自 Web 應用程序的 PDF 文件的有用資源。
規格
- 分頁媒體模塊
- 碎片化
文章和資源
- 使用 CSS 進行打印設計
- 用 CSS 分片打破盒子
- 2018 年打印樣式表狀態指南
- 無頭 Chrome 和 Puppeteer 入門
- 打印-css.rocks
工具
- wkhtmltopdf
- paged.js
- Vivliostyle
- 王子
- 天線屋
- PDF反應器
- 猛禽博士
- WeasyPrint
- PDF人群
- mPDF
- jsPDF
- pdf製作
- 生產和發布服務器