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的魅力。
展示的版本為當期那最新版本3.0.5:
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>3.0.5</version>
</dependency>
3.1 文本提取
文本提取的關鍵類: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使用完畢之后需要關閉資源,類似JDK中的流。這里使用try-with-resources自動關閉資源。案例提取了一張網(wǎng) 約車發(fā)票的信息。
結(jié)果展示

3.2 PDF合并
PDF合并的關鍵類是: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"));
// 設置合并后的pdf名稱
pdfMerger.setDestinationFileName("merge-fp.pdf");
// pdfMerger.setDestinationStream(new FileOutputStream(file));
pdfMerger.mergeDocuments(MemoryUsageSetting.setupMainMemoryOnly().streamCache);
System.out.println("PDF文件合并完成");
}
通過addSource()方法,添加要合并的PDF資源。然后設置合并后的PDF名稱,也可以通過setDestinationStream()指定合并的PDF保存的位置。
執(zhí)行結(jié)果
默認保存在項目的根路徑下面:

3.3 提取圖像
提取PDF中圖像的關鍵類: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 增加簽章
增加簽章的關鍵類: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);
// 設置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)存泄露的風險
用完必須關閉文檔對象。推薦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設計和強大的底層能力,成為Java開發(fā)者處理PDF的首選利器。無論是自動化報表生成還是文檔分析系統(tǒng),它都能提供可靠支持。結(jié)合本文的代碼示例與避坑指南,可快速構(gòu)建穩(wěn)健的PDF處理流程。
以上就是Java使用PDFBox處理PDF的完全指南的詳細內(nèi)容,更多關于Java PDFBox處理PDF的資料請關注腳本之家其它相關文章!
相關文章
Spring實戰(zhàn)之XML與JavaConfig的混合配置詳解
大家都知道Spring的顯示配置方式有兩種,一種是基于XML配置,一種是基于JavaConfig的方式配置。那么下這篇文章主要給大家分別介紹如何在JavaConfig中引用XML配置的bean以及如何在XML配置中引用JavaConfig,需要的朋友可以參考下。2017-07-07
Java實現(xiàn)郵箱發(fā)送功能實例(阿里云郵箱推送)
這篇文章主要給大家介紹了關于Java實現(xiàn)郵箱發(fā)送功能的相關資料,利用阿里云郵箱推送,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-09-09
SpringSecurity Oauth2訪問令牌續(xù)期問題
這篇文章主要介紹了SpringSecurity Oauth2訪問令牌續(xù)期問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2025-04-04
Springboot參數(shù)校驗之分組校驗、嵌套校驗的實現(xiàn)
日常開發(fā)中,免不了需要對請求參數(shù)進行校驗,諸如判空,長度,正則,集合等,復雜一點的請求參數(shù)可能會包含嵌套,分組校驗,本文就詳細的介紹一下,感興趣的可以了解一下2023-08-08
MyBatis的collection和association的使用解讀
這篇文章主要介紹了MyBatis的collection和association的使用解讀2023-12-12

