Java使用PDFBox處理PDF的完全指南
01 引言
在日常開發(fā)中,我們可能會遇到PDF
的處理,如PDF
的內(nèi)容提取、分割、合并等操作。你們都是用什么工具操作的呢?
今天介紹一款Apache
出品的工具PDFBox
,作為Apache
基金會開源項目,它以輕量級、高擴展性著稱,完美解決PDF
的解析、生成與操作難題。
官網(wǎng)地址:pdfbox.apache.org/
02 核心功能一覽
Apache PDFBox
庫是用于處理PDF
文檔的開源 Java 工具。此項目允許創(chuàng)建新的 PDF
文檔、作現(xiàn)有文檔以及從文檔中提取內(nèi)容的能力。Apache PDFBox
還包括幾個命令行實用程序。Apache PDFBox
在 Apache
許可證 v2.0
下發(fā)布。
主要有8個功能:
- 從
PDF
文件提取中文本 PDF
的合并和分割- 從
PDF
表單中提取數(shù)據(jù),或填充PDF
表單 - 驗證
PDF
否符合PDF/A-1b
標準 - 使用標準的
Java
打印API
打印PDF
文件 - 將
PDF
文件另存為圖像格式 - 從零開始創(chuàng)建
PDF
文件,包括嵌入字體和圖像 - 對
PDF
文件進行數(shù)字簽名
03 功能展示
Apache PDFBox
主要提供了8個功能,通過演示幾個常用的功能,了解一下Apache PDFBox
的魅力。
展示的版本為當(dāng)期那最新版本3.0.5
:
<dependency> <groupId>org.apache.pdfbox</groupId> <artifactId>pdfbox</artifactId> <version>3.0.5</version> </dependency>
3.1 文本提取
文本提取的關(guān)鍵類:org.apache.pdfbox.text.PDFTextStripper
@Test void test01() throws IOException { try (PDDocument pdDocument = Loader.loadPDF(ResourceUtils.getFile("classpath:pdf/wyc-fp.pdf"))){ PDFTextStripper textStripper = new PDFTextStripper(); String text = textStripper.getText(pdDocument); System.out.println(text); } }
因為PDDocument
使用完畢之后需要關(guān)閉資源,類似JDK
中的流。這里使用try-with-resources
自動關(guān)閉資源。案例提取了一張網(wǎng) 約車發(fā)票的信息。
結(jié)果展示
3.2 PDF合并
PDF合并的關(guān)鍵類是:org.apache.pdfbox.multipdf.PDFMergerUtility
@Test void test02() throws IOException { PDFMergerUtility pdfMerger = new PDFMergerUtility(); pdfMerger.addSource(ResourceUtils.getFile("classpath:pdf/wyc-fp.pdf")); pdfMerger.addSource(ResourceUtils.getFile("classpath:pdf/wyc-fp2.pdf")); // 設(shè)置合并后的pdf名稱 pdfMerger.setDestinationFileName("merge-fp.pdf"); // pdfMerger.setDestinationStream(new FileOutputStream(file)); pdfMerger.mergeDocuments(MemoryUsageSetting.setupMainMemoryOnly().streamCache); System.out.println("PDF文件合并完成"); }
通過addSource()
方法,添加要合并的PDF
資源。然后設(shè)置合并后的PDF
名稱,也可以通過setDestinationStream()
指定合并的PDF
保存的位置。
執(zhí)行結(jié)果
默認保存在項目的根路徑下面:
3.3 提取圖像
提取PDF
中圖像的關(guān)鍵類:org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject
@Test void test03() throws Exception { try (PDDocument pdDocument = Loader.loadPDF(ResourceUtils.getFile("classpath:pdf/wyc-fp.pdf"));) { // 獲取第一頁:因為只有一頁 PDPage page = pdDocument.getPage(0); PDResources resources = page.getResources(); Iterable<COSName> xObjectNames = resources.getXObjectNames(); for (COSName xObjectName : xObjectNames) { // 判斷是否包含圖片對象 if (resources.isImageXObject(xObjectName)) { PDImageXObject imageObject = (PDImageXObject) resources.getXObject(xObjectName); BufferedImage bImage = imageObject.getImage(); // 將圖像保存為 PNG 格式 try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) { // 將圖片寫入輸出流里面 ImageIO.write(bImage, "png", baos); byte[] imageBytes = baos.toByteArray(); String imageFilePath = "image_" + System.currentTimeMillis() + ".png"; try (FileOutputStream fos = new FileOutputStream(imageFilePath)) { fos.write(imageBytes); System.out.println("Page Image path: " + imageFilePath); } } } } } }
通過resources.getXObject(xObjectName)
獲取圖像資源,通過ImageIO.write()
寫到輸出流里面
執(zhí)行結(jié)果
可以看出打印和輸出的圖片名稱和圖片。提取出了那些圖片呢?
這里為了方便截圖,將三張圖展示在了一起。
3.4 增加簽章
增加簽章的關(guān)鍵類:org.apache.pdfbox.pdmodel.PDPageContentStream
@Test void test04() throws Exception { PDDocument pdDocument = Loader.loadPDF(ResourceUtils.getFile("classpath:pdf/wyc-fp.pdf")); PDImageXObject pdImage = PDImageXObject.createFromFile("src/main/resources/pdf/apache-logo.jpg", pdDocument); // 設(shè)置logo的寬度和高度 float imageWidth = 100; float imageHeight = 100; if (pdDocument != null) { PDPage page = pdDocument.getPage(pdDocument.getNumberOfPages() - 1); float pageWidth = page.getMediaBox().getWidth();; // 計算logo位置:頁面右下角 float x = pageWidth - imageWidth - 20; // 右邊距20 float y = 20; // 下邊距20 // 為最后一頁創(chuàng)建一個新的內(nèi)容流以添加logo try (PDPageContentStream contentStream = new PDPageContentStream(pdDocument, page, PDPageContentStream.AppendMode.APPEND, true, true)) { // 繪制logo圖片 contentStream.drawImage(pdImage, x, y, imageWidth, imageHeight); } pdDocument.save("logo_" + System.currentTimeMillis() + ".pdf"); // 保存修改后的PDF } }
這里的簽章用的是Apache
的logo
。將簽章放在右下角。
執(zhí)行結(jié)果
04 避坑指南
4.1 內(nèi)存泄露的風(fēng)險
用完必須關(guān)閉文檔對象。推薦Try-with-resources
:
try (PDDocument pdDocument = Loader.loadPDF(file)){ // *** }
4.2 版本差異
2.0.x
與3.0
存在API
部分不兼容,如:
// 2.0.x 加載文件 PDDocument.load(file) // 3.0 加載文件 Loader.loadPDF(file)
4.3 JDK版本要求差異
2.0.x
與3.0
對JDK
版本最低要求不一樣
# 2.0.x 最低要求:JDK1.6 # 3.0 最低要求:JDK1.8
05 小結(jié)
Apache PDFBox
以其簡潔的API
設(shè)計和強大的底層能力,成為Java
開發(fā)者處理PDF
的首選利器。無論是自動化報表生成還是文檔分析系統(tǒng),它都能提供可靠支持。結(jié)合本文的代碼示例與避坑指南,可快速構(gòu)建穩(wěn)健的PDF
處理流程。
以上就是Java使用PDFBox處理PDF的完全指南的詳細內(nèi)容,更多關(guān)于Java PDFBox處理PDF的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java數(shù)據(jù)結(jié)構(gòu)BFS廣搜法解決迷宮問題
廣搜BFS的基本思想是: 首先訪問初始點v并將其標志為已經(jīng)訪問。接著通過鄰接關(guān)系將鄰接點入隊。然后每訪問過一個頂點則出隊。按照順序,訪問每一個頂點的所有未被訪問過的頂點直到所有的頂點均被訪問過。廣度優(yōu)先遍歷類似與層次遍歷2022-04-04IDEA無法識別相關(guān)module模塊問題的解決過程
這篇文章主要給大家介紹了關(guān)于IDEA無法識別相關(guān)module模塊問題的解決過程,文中通過圖文介紹的非常詳細,對大家學(xué)習(xí)或者使用IDEA具有一定的參考借鑒價值,需要的朋友可以參考下2023-07-07詳解Java使用sqlite 數(shù)據(jù)庫如何生成db文件
這篇文章主要介紹了詳解Java 操作sqllite 數(shù)據(jù)庫如何生成db文件的相關(guān)資料,需要的朋友可以參考下2017-07-07Windows10系統(tǒng)下JDK1.8環(huán)境變量的配置
今天帶大家學(xué)習(xí)在Windows10系統(tǒng)下怎么配置JDK1.8環(huán)境變量,文中有非常詳細的安裝及配置教程,對正在學(xué)習(xí)的小伙伴們很有幫助,需要的朋友可以參考下2021-05-05Spring Boot中Bean定義方調(diào)用方式解析
這篇文章主要介紹了Spring Boot中Bean定義方調(diào)用方式解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2020-07-07