目錄
样式控制
首頁 web前端 html教學 HTML轉成PDF的4個方法介紹(附程式碼)

HTML轉成PDF的4個方法介紹(附程式碼)

Mar 30, 2019 am 10:57 AM
node.js pdf 前端

這篇文章帶給大家的內容是關於把HTML轉成PDF的4個方法介紹(附程式碼),有一定的參考價值,有需要的朋友可以參考一下,希望對你有幫助。

在本文中,我將展示如何使用 Node.js、Puppeteer、headless Chrome 和 Docker 從樣式複雜的 React 頁面產生 PDF 文件。

背景:幾個月前,有個客戶要求我們開發一個功能,使用者可以得到 PDF 格式的 React 頁面內容。該頁面基本上是患者病例的報告和數據視覺化結果,其中包含許多 SVG。另外還有一些特殊的請求來操縱佈局,並對 HTML 元素進行一些重新排列。因此與原始的 React 頁面相比,PDF 中應該有不同的樣式和額外的內容。

由於這個任務比用簡單的 CSS 規則解決要複雜得多,所以我們先探討了可能的實作方法。我們找到了 3 個主要解決方案。這篇部落格文章將引導你了解它們的可能性並最終實施。

在客戶端還是伺服器端產生?

在客戶端和伺服器端都可以產生PDF檔案。但是讓後端處理它可能更有意義,因為你不想耗盡用戶瀏覽器可以提供的所有資源。

即便如此,我仍然會展示這兩種方法的解決方案。

方案1:從 DOM 製作螢幕截圖

乍一看,這個解決方案似乎是最簡單的,事實證明的確是這樣,但它有其自身的限制。如果你沒有特殊需求,例如在 PDF 中選擇文字或對文字進行搜索,那麼這就是一種簡單易用的方法。

此方法簡單明了:從頁面建立螢幕截圖,並把它放到 PDF 檔案中。非常直截了當。我們可以使用兩個套件來實作:

  • Html2canvas,根據DOM 產生截圖
  • jsPdf,一個產生PDF的函式庫
##開始編碼:

npm install html2canvas jspdf

import html2canvas from 'html2canvas'
import jsPdf from 'jspdf'
 
function printPDF () {
    const domElement = document.getElementById('your-id')
    html2canvas(domElement, { onclone: (document) => {
      document.getElementById('print-button').style.visibility = 'hidden'
}})
    .then((canvas) => {
        const img = canvas.toDataURL('image/png')
        const pdf = new jsPdf()
        pdf.addImage(imgData, 'JPEG', 0, 0, width, height)
        pdf.save('your-filename.pdf')
})
登入後複製
就這樣!

請注意 html2canvas 的 onclone方法。當你在截圖之前需要操縱 DOM(例如隱藏列印按鈕)時,它是非常方便的。我看到很多使用這個包的項目。但不幸的是,這不是我們想要的,因為我們需要在後端完成對 PDF 的建立工作。

方案2:只使用 PDF 函式庫

NPM上有幾個函式庫,如 jsPDF(如上所述)或PDFKit。他們的問題是,如果我想使用這些庫,我將不得不重新調整頁面結構。這肯定會損害可維護性,因為我需要將所有後續變更套用到 PDF 範本和 React 頁面中。

請看下面的程式碼。你需要親自手動建立 PDF 文件。你需要遍歷 DOM 並找出每個元素並將其轉換為 PDF 格式,這是一項繁瑣的工作。必須找到一個更簡單的方法。

doc = new PDFDocument
doc.pipe fs.createWriteStream('output.pdf')
doc.font('fonts/PalatinoBold.ttf')
   .fontSize(25)
   .text('Some text with an embedded font!', 100, 100)
 
doc.image('path/to/image.png', {
   fit: [250, 300],
   align: 'center',
   valign: 'center'
});
 
doc.addPage()
   .fontSize(25)
   .text('Here is some vector graphics...', 100, 100)
 
doc.end()
登入後複製
這段程式碼片段來自 PDFKit 文件。但是如果你的目標是直接產生一個 PDF 文件,而不是對一個已經存在的(並且不斷變化的)HTML 頁面進行轉換,它還是很有用的。

最終方案3:基於 Node.js 的 Puppeteer 和 Headless Chrome

什麼是 Puppeteer?其文件中寫道:


Puppeteer 是一個 Node 函式庫,它提供了一個進階 API 來控制 DevTools 協定上的 Chrome 或 Chromium。 Puppeteer 預設以 headless 模式執行 Chrome 或 Chromium,但其也可以被配置為完整的(non-headless)模式運作。
它本質上是一個可以從 Node.js 運行的瀏覽器。如果你有讀過它的文檔,其中首先提到的就是你可以用 Puppeteer 來

產生頁面的截圖和PDF。優秀!這正是我們想要的。

先用

npmi i puppeteer 安裝 Puppeteer,實現我們的功能。

const puppeteer = require('puppeteer')
 
async function printPDF() {
  const browser = await puppeteer.launch({ headless: true });
  const page = await browser.newPage();
  await page.goto('https://blog.risingstack.com', {waitUntil: 'networkidle0'});
  const pdf = await page.pdf({ format: 'A4' });
 
  await browser.close();
  return pdf
})
登入後複製
這是一個簡單的功能,可導航到 URL 並產生網站的 PD F檔案。

首先,我們啟動瀏覽器(僅在 headless 模式下支援 PDF 產生),然後開啟新頁面,設定視窗,並導航到提供的URL。

設定

waitUntil:'networkidle0' 選項表示當至少500毫秒沒有網路連線時,Puppeteer 會認為導覽已完成。 (可以從 API docs 取得更多資訊。)

之後,我們將 PDF 儲存為變量,關閉瀏覽器並返回 PDF。

注意:

page.pdf 方法接收 options 對象,你可以使用 'path' 選項將檔案儲存到磁碟。如果未提供路徑,則 PDF 將不會被儲存到磁碟,而是會得到緩衝區。 (稍後我將討論如何處理它。)

如果需要先登入才能從受保護的頁面產生PDF,首先你要導航到登入頁面,檢查表單元素的ID 或名稱,填寫它們,然後提交表單:

await page.type('#email', process.env.PDF_USER)
await page.type('#password', process.env.PDF_PASSWORD)
await page.click('#submit')
登入後複製
要始終將登入憑證保存在環境變數中,不要硬編碼!

样式控制

Puppeteer 也有这种样式操作的解决方案。你可以在生成 PDF 之前插入样式标记,Puppeteer 将生成具有已修改样式的文件。

await page.addStyleTag({ content: '.nav { display: none} .navbar { border: 0px} #print-button {display: none}' })
登入後複製

将文件发送到客户端并保存

好的,现在你已经在后端生成了一个 PDF 文件。接下来做什么?

如上所述,如果你不把文件保存到磁盘,将会得到一个缓冲区。你只需要把含有适当内容类型的缓冲区发送到前端即可。

printPDF.then(pdf => {
    res.set({ 'Content-Type': 'application/pdf', 'Content-Length': pdf.length })
    res.send(pdf)
登入後複製

现在,你只需在浏览器向服务器发送请求即可得到生成的 PDF。

function getPDF() {
 return axios.get(`${API_URL}/your-pdf-endpoint`, {
   responseType: 'arraybuffer',
   headers: {
     'Accept': 'application/pdf'
   }
 })
登入後複製

一旦发送了请求,缓冲区的内容就应该开始下载了。最后一步是将缓冲区数据转换为 PDF 文件。

savePDF = () => {
    this.openModal(‘Loading…’) // open modal
   return getPDF() // API call
     .then((response) => {
       const blob = new Blob([response.data], {type: 'application/pdf'})
       const link = document.createElement('a')
       link.href = window.URL.createObjectURL(blob)
       link.download = `your-file-name.pdf`
       link.click()
       this.closeModal() // close modal
     })
   .catch(err => /** error handling **/)
 }
<button onClick={this.savePDF}>Save as PDF</button>
登入後複製

就这样!如果单击“保存”按钮,那么浏览器将会保存 PDF。

在 Docker 中使用 Puppeteer

我认为这是实施中最棘手的部分 —— 所以让我帮你节省几个小时的百度时间。

官方文档指出“在 Docker 中使用 headless Chrome 并使其运行起来可能会非常棘手”。官方文档有疑难解答部分,你可以找到有关用 Docker 安装 puppeteer 的所有必要信息。

如果你在 Alpine 镜像上安装 Puppeteer,请确保在看到页面的这一部分时再向下滚动一点。否则你可能会忽略一个事实:你无法运行最新的 Puppeteer 版本,并且你还需要用一个标记禁用 shm :

const browser = await puppeteer.launch({
  headless: true,
  args: ['--disable-dev-shm-usage']
});
登入後複製

否则,Puppeteer 子进程可能会在正常启动之前耗尽内存。

方案 3 + 1:CSS 打印规则

可能有人认为从开发人员的角度来看,简单地使用 CSS 打印规则很容易。没有 NPM 模块,只有纯 CSS。但是在跨浏览器兼容性方面,它的表现如何呢?

在选择 CSS 打印规则时,你必须在每个浏览器中测试结果,以确保它提供的布局是相同的,并且它不是100%能做到这一点。

例如,在给定元素后面插入一个 break-after 并不是一个多么高深的技术,但是你可能会惊讶的发现要在 Firefox 中使用它需要使用变通方法。

除非你是一位经验丰富的 CSS 大师,在创建可打印页面方面有很多的经验,否则这可能会非常耗时。

如果你可以使打印样式表保持简单,打印规则是很好用的。

让我们来看一个例子吧。

@media print {
    .print-button {
        display: none;
    }
    
    .content p {
        break-after: always;
    }
}
登入後複製

上面的 CSS 隐藏了打印按钮,并在每个 p 之后插入一个分页符,其中包含content 类。有一篇很棒的文章总结了你可以用打印规则做什么,以及它们有什么问题,包括浏览器兼容性。

考虑到所有因素,如果你想从不那么复杂的页面生成 PDF,CSS打印规则非常有效。

总结

让我们快速回顾前面介绍的方案,以便从 HTML 页面生成 PDF 文件:

从 DOM 产生截图:当你需要从页面创建快照时(例如创建缩略图)可能很有用,但是当你需要处理大量数据时就会有些捉襟见肘。

只用 PDF 库:如果你打算从头开始以编程方式创建 PDF 文件,这是一个完美的解决方案。否则,你需要同时维护 HTML 和 PDF 模板,这绝对是一个禁忌。

Puppeteer:尽管在 Docker 上工作相对困难,但它为我们的实现提供了最好的结果,而且编写代码也是最简单的。

CSS打印规则:如果你的用户受过足够的教育,知道如何把页面内容打印到文件,并且你的页面相对简单,那么它可能是最轻松的解决方案。正如你在我们的案例中所看到的,事实并非如此。

本篇文章到这里就已经全部结束了,更多其他精彩内容可以关注PHP中文网的HTML视频教程栏目!

以上是HTML轉成PDF的4個方法介紹(附程式碼)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

如何在 iPhone 上合併 PDF 如何在 iPhone 上合併 PDF Feb 02, 2024 pm 04:05 PM

在處理多個文件或同一文件的多個頁面時,您可能會想要將它們合併到一個文件中以與他人共用。為了方便共享,Apple允許您將多個PDF文件合併為一個文件,避免發送多個文件。在這篇文章中,我們將幫助您了解在iPhone上將兩個或多個PDF合併為一個PDF文件的所有方法。如何在iPhone上合併PDF在iOS上,您可以透過兩種方式將PDF檔案合併為一個–使用「檔案」應用程式和「捷徑」應用程式。方法1:使用「文件」應用將兩個或多個PDF合併為一個文件的最簡單方法是使用「文件」應用程式。在iPhone上打開

在iPhone上從PDF取得文字的3種方法 在iPhone上從PDF取得文字的3種方法 Mar 16, 2024 pm 09:20 PM

Apple的即時文字功能可識別照片中或透過相機應用程式的文字、手寫筆記和數字,並允許您將該資訊貼到任何其他應用程式上。但是,當您處理PDF並想要從中提取文字時該怎麼辦?在這篇文章中,我們將解釋在iPhone上從PDF文件中提取文字的所有方法。如何在iPhone上從PDF文件中獲取文字[3種方法]方法1:在PDF上拖曳文字從PDF中提取文字的最簡單方法就是複製它,就像在任何其他帶有文字的應用程式上一樣。 1.開啟要從中提取文字的PDF文件,然後長按PDF上的任意位置並開始拖曳要複製的文字部分。 2

如何在PDF中驗證簽名 如何在PDF中驗證簽名 Feb 18, 2024 pm 05:33 PM

我們通常會接收到政府或其他機構發送的PDF文件,有些文件有數位簽章。驗證簽名後,我們會看到SignatureValid訊息和一個綠色勾號。如果簽章未驗證,會顯示有效性未知。驗證簽名很重要,以下看看如何在PDF中進行驗證。如何在PDF中驗證簽名驗證PDF格式的簽名使其更可信,文件更容易被接受。您可以透過以下方式驗證PDF文件中的簽名。在AdobeReader中開啟PDF右鍵點選簽名,然後選擇顯示簽名屬性點選顯示簽署者憑證按鈕從「信任」標籤將簽名新增至「受信任的憑證」清單中點選驗證簽名以完成驗證讓

xmind文件怎麼匯出為pdf文件 xmind文件怎麼匯出為pdf文件 Mar 20, 2024 am 10:30 AM

xmind是一款非常實用的心智圖軟體,它是利用人們的思維和靈感製作出來的導圖形式,我們在製作完xmind檔案通常會把它轉換成pdf檔格式,以方便大家傳播使用,那麼xmind檔怎麼匯出為pdf檔呢?以下就是具體操作步驟可以供大家參考。 1.首先我們來示範如何匯出心智圖為PDF文件。選擇【檔案】-【匯出】功能按鈕。 2.在新出現的介面中選擇【PDF文件】並點選【下一步】按鈕。 3.在匯出介面選擇設定:紙張尺寸、方向、解析度和文件儲存位置。完成設定後點選【完成】按鈕。 4.如果點選【完成】按鈕後

解決PHP7下載PDF檔案遇到的問題 解決PHP7下載PDF檔案遇到的問題 Feb 29, 2024 am 11:12 AM

解決PHP7下載PDF檔案遇到的問題在Web開發中,常常會遇到使用PHP下載檔案的需求。特別是下載PDF文件,能夠幫助使用者取得必要的資訊或文件。然而,有時候在PHP7下載PDF檔案會遇到一些問題,例如出現亂碼、下載不完整等情況。本文將詳細介紹如何解決在PHP7下載PDF檔案時可能遇到的問題,並提供一些具體的程式碼範例。問題分析在PHP7中,由於字元編碼、H

學習如何使用edge瀏覽器的快捷鍵旋轉PDF文件 學習如何使用edge瀏覽器的快捷鍵旋轉PDF文件 Jan 05, 2024 am 09:17 AM

pdf檔雖然使用起來非常的方便,但是還是很多小夥伴喜歡用word去進行編輯和查看,那麼該怎麼去進行轉換呢?下面就一起來看看詳細的操作方法吧。 edge瀏覽器pdf旋轉快速鍵:答:旋轉的快速鍵為F9。1.右鍵點選pdf檔選擇「開啟方式」。 2、選擇「Microsoftedge」開啟pdf檔。 3.進入pdf檔後下方會出現工作列。 4.點選「+」號邊上的旋轉按鍵,即可進行向右旋轉。

win11如何設定PDF預設開啟方式 win11設定PDF預設開啟方式教學 win11如何設定PDF預設開啟方式 win11設定PDF預設開啟方式教學 Feb 29, 2024 pm 09:01 PM

有使用者覺得每次開啟PDF檔案都要選擇一個開啟方式很麻煩,想要將自己常用的開啟方式設定為預設方式,那麼win11如何設定PDF預設開啟方式呢?下面小編就跟大家詳細介紹win11設定PDF預設開啟方式教程,大家有興趣的話就來看看吧。 win11設定PDF預設開啟方式教學1、快速鍵"win+R"開啟運行,輸入"ms-settings:defaultapps"指令,回車開啟。 2.進入新介面後,在上方搜尋框中輸入".pdf",點選搜尋圖示進行搜尋。 3、這

PHP與Vue:完美搭檔的前端開發利器 PHP與Vue:完美搭檔的前端開發利器 Mar 16, 2024 pm 12:09 PM

PHP與Vue:完美搭檔的前端開發利器在當今網路快速發展的時代,前端開發變得愈發重要。隨著使用者對網站和應用的體驗要求越來越高,前端開發人員需要使用更有效率和靈活的工具來創建響應式和互動式的介面。 PHP和Vue.js作為前端開發領域的兩個重要技術,搭配起來可以稱得上是完美的利器。本文將探討PHP和Vue的結合,以及詳細的程式碼範例,幫助讀者更好地理解和應用這兩

See all articles