JavaScrip教程 | 如何使用JavaScript從PDF中提取并渲染頁面

本文目錄
首先,我們將探索一些流行的 PDF 包,用于 JavaScript 中與 PDF 相關(guān)的工作。然后,我們將對它們進行比較,找到適合我們要求的最佳軟件包。
接下來,我們將加載一個現(xiàn)有的 PDF,并從中提取一些頁面。提取的頁面將組成一個新的 PDF 文檔。
然后,我們將在瀏覽器中渲染新的 PDF(我們在第二步中制作的)。
最后,我們將下載新的 PDF 文件供以后使用。
用于 JavaScript 的 PDF 庫
我發(fā)現(xiàn) JavaScript 中的 PDF 庫主要有兩種類型。一種是用于 PDF 渲染生成,另一種是用于 PDF 操作(或修改)。我在搜索了一個多小時后發(fā)現(xiàn)了一堆 PDF 庫,這些是我最好的選擇。
這里列出的所有軟件包都是免費的、開源的軟件包。你可以在 npm 注冊表中找到所有這些包。
pdfjs
該軟件包由 Firefox 網(wǎng)絡(luò)瀏覽器背后的公司 Mozilla 制作。 pdfjs 是一個基于 Web 標準的解析和呈現(xiàn) PDF 的平臺。
當您在 Firefox 中查看 PDF 時,PDF 查看器是使用此 pdfjs 包制作的。
這個包的核心優(yōu)勢是在網(wǎng)頁上進行 PDF 渲染。其他的 PDF 修改功能在這個包里是非常有限的。如果你想為你的網(wǎng)站制作一個自定義的 PDF 瀏覽器,這可能是你正在尋找的軟件包。
pdfjs 有一個非常簡單的 API。他們有很多教程可以讓你開始使用這個庫。如果你還不相信,可以使用這個庫一段時間,你一定會愛上它的。
pdf-lib
與之前的 pdfjs 包不同,pdf-lib 主要用于 PDF 的創(chuàng)建和操作。你可以根據(jù)你的需要用這個包動態(tài)地生成一個新的 PDF 文檔。
這個包對修改現(xiàn)有文檔有強大的支持。你可以用這個庫做很多 PDF 的修改。例如,你可以做 PDF 的分割和合并,你可以提取一個頁面,注釋一個 PDF 文檔,添加一個大綱,以及更多你能想象的事情。
它只有 JavaScript 作為一個依賴項。所以,它可以運行在任何有 JavaScript 運行時間的設(shè)備上。瀏覽器、Nodejs、Deno 和 React Native 都得到良好的支持。如果能在設(shè)備上安裝 JavaScript,那么這個庫就肯定能工作。
pdf-lib 的主要缺點是,它沒有強大的渲染支持。如果你想用這個庫做一個漂亮的 PDF 瀏覽用戶界面,那么 pdf-lib 不是你的正確選擇。在這種情況下,你應(yīng)該使用 pdfjs 來代替。
pdfjs?#2
如果你認為我在重復(fù)自己的話(跟 Mozilla 維護的?pdfjs
?不一樣),那么我沒有。這是一個用于創(chuàng)建 PDF 文檔的 JavaScript 庫。它有一個非常簡單的 API 可以使用。
我們之前討論過的 pdfjs 庫在用戶界面上有非常強大的渲染支持,但它缺乏 PDF 創(chuàng)建和修改功能。
但這個庫是以創(chuàng)建 PDF 為目的而建立的。它有一個非常簡單的 API,對初學(xué)者很友好。你可以將它與 pdf-lib 包進行比較。
這個 pdfjs 庫的主要缺點是,對現(xiàn)有文件的修改支持仍處于測試階段。它并不是很穩(wěn)定,而且仍在進行中。
如果你的主要關(guān)注點是 PDF 修改(例如,頁面提取、合并、拆分、注釋等),那么這個庫可能不適合你。
如果貢獻者能夠進行維護,那么這可能是對 JavaScript 來說最好的 PDF 包。
js-pdf
與上面列出的所有 PDF 包不同,這個庫是一個完整的野獸。你可以用這個庫做任何與 PDF 有關(guān)的工作。這就像一個萬能的庫。如果你想要一些復(fù)雜的 PDF 相關(guān)的東西,那么這個庫可以做到。
但在 JavaScript 中還有更好的包,它們對個別任務(wù)非常好。例如,pdfjs 是一個比 js-pdf 更好的 PDF 渲染器,而 pdf-lib 比 js-pdf 有更好的修改支持。
這里我說的不是實際性能或其他類型的指標,我說的是開發(fā)者的體驗。我發(fā)現(xiàn)它的 API 不是很直觀。對于一個初學(xué)者來說,第一眼就會感到不知所措。不過,這是我的看法,也是我使用它時的體驗
PDF 生成是這個庫的主要優(yōu)勢。你可以用你的任何設(shè)計來生成任何類型的 PDF。這個軟件包將為你完成所有繁重的工作。如果你有經(jīng)驗,那么這可能是你的最佳選擇。
react-pdf
顧名思義,這個庫是專門針對 React 生態(tài)系統(tǒng)的。其用法非常具有 React 風(fēng)格。你可以用它類似 JSX 的語法輕松創(chuàng)建一個文檔。
你可以用簡單的 React 組件創(chuàng)建和顯示一個 PDF 文檔。但功能非常有限。這個庫主要用于生成 PDF。
如果你的目標是向用戶展示一個 PDF,那么你可以使用這個包。作為一個 React 愛好者,你會喜歡這個庫??纯此麄兊挠螛穲?,花些時間來使用這個包。這樣你就會知道你是否需要這個庫。
為什么我們要在本教程中使用 pdf-lib?
在上面提到的所有這些 PDF 庫中,我將在本文中使用 pdf-lib。因為我們要分割和合并 PDF 頁面,并在瀏覽器中渲染它們,pdf-lib 似乎是這種情況下的最佳選擇。
而且,pdf-lib 有相當簡單的 API 可以使用,所有這些 API 都有很好的文檔。如果你使用 TypeScript,你還可以獲得類型推導(dǎo),這非常有幫助。
最后但同樣重要的是,他們的例子非常好。你可以在幾分鐘內(nèi)啟動并運行。所以我喜歡這個庫,因為它適合我的使用情況。
如何在 JavaScript 中讀取本地 PDF 文件
在對我們的 PDF 文檔進行任何操作之前,我們必須從用戶那里讀取到該文檔。在瀏覽器中讀取任何文件都可以通過FileReader
?web API 來處理。
首先,我們要做一個文件輸入按鈕,然后用FileReader
網(wǎng)絡(luò) API 處理上傳的文件。
由于 Filereader API 是用回調(diào)工作的,我發(fā)現(xiàn) async/await 要簡明得多,也更容易操作。所以讓我們做一個輔助函數(shù),把 Filereader 的回調(diào)修改成 async/await。
現(xiàn)在,當用戶使上傳文件完成時,我們監(jiān)聽文件輸入事件,然后使用這個readFileAsync
函數(shù)讀取文件。
這個邏輯的實現(xiàn)在代碼中看起來像這樣:
如何提取 PDF 頁面
到此為止,我們的 PDF 被上傳并轉(zhuǎn)換為 JavaScript?ArrayBuffer
。由于我們正在從 PDF 中提取一系列的頁面,我們想要一個包含 PDF 中這些頁碼的數(shù)組。
在 JavaScript 中生成一個自然數(shù)的數(shù)組并不難。所以我們做了一個名為range()
的函數(shù)來生成我們想要的所有索引。
我們必須提供起始頁數(shù)和結(jié)束頁數(shù),然后這個range()
函數(shù)就可以生成一個帶有適當頁數(shù)的數(shù)組。
在這里,我們在最后加上?-1
。你知道原因是什么嗎?在編程中,索引是從 0 開始的,而不是 1。所以我們必須從每一個頁碼中扣除-1,以獲得我們想要的行為。
現(xiàn)在讓我們開始本文的主要部分:提取。在做任何工作之前,請導(dǎo)入 pdf-lib 庫。
首先,我們加載我們從之前的onFileSelected'函數(shù)得到的PDF
ArrayBuffer'。然后我們把ArrayBuffer
加載到PDFDocument.load(arraybuffer)
函數(shù)中。這就是我們的用戶提供的 PDF。為了方便起見,我們稱它為pdfSrcDoc
。
現(xiàn)在我們將創(chuàng)建一個新的 PDF。所有從用戶提供的文檔中提取的 PDF 頁面都被合并到新文檔中。我們使用PDFDocument.create()
函數(shù)來做這件事。為了便于使用,我們稱它為pdfNewDoc
。
之后,我們使用copyPages()
函數(shù)將我們想要的頁面從pdfSrcDoc
復(fù)制到pdfNewDoc
。然后我們將復(fù)制的頁面添加到`pdfNewDoc'中。
要保存這些變化,運行pdfNewDoc.save()
。讓我們創(chuàng)建一個名為extractPdfPage()
的函數(shù)來重用這個邏輯。函數(shù)中的代碼將看起來像這樣:
我們從extractPdfPage()
函數(shù)返回一個Uint8Array
。
如何在瀏覽器中渲染 PDF
到目前為止,我們有一個修改過的 PDF 的Uint8Array
。為了在你的瀏覽器中呈現(xiàn)它,我們必須把它轉(zhuǎn)換成一個 Blob。
然后我們將它做成一個 URL,并在一個 iframe 中呈現(xiàn)。
你也可以使用我上面提到的 pdfjs 庫制作你的自定義 PDF 瀏覽器。但如果你不需要顯示品牌和定制,瀏覽器的默認 PDF 查看器就可以達到這個目的。
現(xiàn)在你可以很容易地在一個?iframe
?中渲染這個從?renderPdf()
?函數(shù)返回的 docUrl。
完整的代碼示例
我在本教程中使用 Next.js。如果你使用的是其他框架或 vanilla JavaScript,結(jié)果也會類似。下面是這個項目的所有代碼:
現(xiàn)在你可以使用 PDF 查看器上的下載按鈕保存生成的 PDF。
更多學(xué)習(xí)資料關(guān)注馬哥教育? VX :Teemo--1