开源PDF工具 Apache PDFBox 认识及使用(知识点+案例)
媒介博主先容:✌目前全网粉丝2W+,csdn博客专家、Java领域优质创作者,博客之星、阿里云平台优质作者、专注于Java后端技能领域。
涵盖技能内容:Java后端、算法、分布式微服务、中间件、前端、运维、ROS等。
博主全部博客文件目录索引:博客目录索引(持续更新)
视频平台:b站-Coder长路
源码获取
项目源码:Gitee、Github
本篇文档的视频系列讲解:Java实现自动化pdf打水印工具 开源PDF工具PDFBoxWord、Word转PDF开源工具Documents4j
一、认识PDFBox
Apache PDFBox库是一个开源的Java工具,专门用于处理PDF文档。它答应用户创建全新的PDF文件,编辑现有的PDF文档,以及从PDF文件中提取内容。
功能:创建、渲染、打印、合并、拆分、加密、解密、签名等多种操作PDF文件的功能,包括一个下令行工具,可以用于实行各种PDF处理使命。支持文本提取和搜索,以及将PDF转换为其他格式,如图片和文本。
应用场景:广泛应用于企业和开发者构建PDF处理干系的应用程序和工具。
Apache PDFBox具备以下主要功能:
[*]从PDF文件中提取Unicode文本。
[*]将单个PDF文件拆分成多个文件,或将多个PDF文件合并成一个。
[*]从PDF表单中提取数据,或填写PDF表单。
[*]验证PDF文件是否符合PDF/A-1b标准。
[*]使用标准的Java打印API打印PDF文件。
[*]将PDF文件另存为图像格式,如PNG或JPEG。
[*]从零开始创建PDF文件,包括嵌入字体和图像。
[*]对PDF文件进行数字签名。
二、导入依赖
<dependencies>
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox</artifactId>
<version>2.0.28</version>
</dependency>
</dependencies>
三、底子功能
demo1:读取pdf全部内容
https://img-blog.csdnimg.cn/img_convert/41ee5c86cf0ec9c0aae98636ee502583.png
package com.changlu.demos;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;
import java.io.File;
import java.net.URLDecoder;
/**
* @Description:
* @Author: changlu
* @Date: 1:28 PM
*/
public class Demo1 {
public static void main(String[] args) throws Exception{
//读取resources目录下input.pdf文件
String inputFile = URLDecoder.decode(Demo1.class.getClassLoader().getResource("input.pdf").getFile(), "UTF-8");
PDDocument pdDocument = PDDocument.load(new File(inputFile));
PDFTextStripper pdfTextStripper = new PDFTextStripper();
//读取pdf中所有的文件
String fullText = pdfTextStripper.getText(pdDocument);
System.out.println(fullText);
}
}
https://img-blog.csdnimg.cn/img_convert/14b1df07d009f2d8be78ec85ae2f3d2b.png
demo2:读取全部页内容(分页)
https://img-blog.csdnimg.cn/img_convert/76ca1c1671d236b0c2c9cbc4862d49a8.png
package com.changlu;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;
import java.io.InputStream;
/**
* @Description:
* @Author: changlu
* @Date: 11:19 AM
*/
public class Main {
public static void main(String[] args) throws Exception{
//读取resources目录下input.pdf文件
InputStream is = Main.class.getClassLoader().getResourceAsStream("input.pdf");
PDDocument pdDocument = PDDocument.load(is);
PDFTextStripper pdfTextStripper = new PDFTextStripper();
//读取所有的分页
for (int i = 1; i <= pdDocument.getNumberOfPages(); i++) {
//设置起始-结束页这里设置指定某页
pdfTextStripper.setStartPage(i);
pdfTextStripper.setEndPage(i);
//读取每一页
String pageText = pdfTextStripper.getText(pdDocument);
System.out.println(String.format("第%s页读取内容:", i));
System.out.println(pageText);
}
}
}
https://img-blog.csdnimg.cn/img_convert/eb15a5e5d5c33c523280384c1d7faea6.png
demo3:添加页眉、页脚
要求:页眉页脚居中体现。
https://img-blog.csdnimg.cn/img_convert/21be6c3b2dd006fc52d2d101f953b35d.png
package com.changlu.demos;
import com.changlu.Main;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDType0Font;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.apache.pdfbox.pdmodel.graphics.state.PDExtendedGraphicsState;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.URLDecoder;
import java.nio.file.Files;
import java.nio.file.Paths;
/**
* @Description: 添加页眉、页脚
* @Author: changlu
* @Date: 1:38 PM
*/
public class Demo3 {
public static void main(String[] args) throws Exception{
//读取resources目录下input.pdf文件
InputStream is = Main.class.getClassLoader().getResourceAsStream("input.pdf");
PDDocument pdDocument = PDDocument.load(is);
//自定义字体 C:\Users\93997\Desktop\watermark tools\watermarkTools\target\classes\ttfs
//URLDecoder.decode() 方法来解码 URL 编码的路径,将 %20 转换回空格
String fontFile = URLDecoder.decode(Main.class.getClassLoader().getResource(File.separator + "ttfs" + File.separator + "Alibaba_PuHuiTi_2.0_65_Medium_65_Medium.ttf").getFile(), "UTF-8");
PDType0Font font = PDType0Font.load(pdDocument, new File(fontFile));
float fontSize = 10; // 设置字体大小为12
// 设置透明度状态对象
PDExtendedGraphicsState graphicsState = new PDExtendedGraphicsState();
graphicsState.setNonStrokingAlphaConstant(0.2f);
graphicsState.setAlphaSourceFlag(true);
graphicsState.setStrokingAlphaConstant(0.2f);
//设置新的页眉
String headerText = "咨询专转本默默学课程联系官方报名处QQ:3503851091,更多资料可加群828303961";
String footerText = "江苏专转本公众号:专转本智慧树";
//遍历原先的pdf文档
for (PDPage page : pdDocument.getPages()) {
float pageWidth = page.getMediaBox().getWidth();
//计算页眉的居中位置
float headerTextWidth = font.getStringWidth(headerText) / 1000 * fontSize;
float headerCenteredX = (pageWidth - headerTextWidth) / 2; // 计算水平居中位置
//计算页脚的居中位置
float footerTextWidth = font.getStringWidth(footerText) / 1000 * fontSize;
float footerCenteredX = (pageWidth - footerTextWidth) / 2; // 计算水平居中位置
// 创建用于页眉的内容流
PDPageContentStream headerContentStream = new PDPageContentStream(pdDocument, page, PDPageContentStream.AppendMode.APPEND, true, true);
headerContentStream.beginText(); // 开始文本操作
headerContentStream.setFont(font, fontSize); // 设置字体和字号
headerContentStream.newLineAtOffset(headerCenteredX, page.getMediaBox().getHeight() - 30); // 设置文本起始位置
headerContentStream.showText(headerText); // 绘制页眉内容
headerContentStream.endText(); // 结束文本操作
headerContentStream.close(); // 关闭内容流
// 添加页脚
PDPageContentStream footerContentStream = new PDPageContentStream(pdDocument, page, PDPageContentStream.AppendMode.APPEND, true, true);
footerContentStream.beginText(); // 开始文本操作
footerContentStream.setFont(font, fontSize); // 设置字体和字号
footerContentStream.newLineAtOffset(footerCenteredX, 30); // 设置文本起始位置
footerContentStream.showText(footerText); // 绘制页脚内容
footerContentStream.endText(); // 结束文本操作
footerContentStream.close(); // 关闭内容流
}
//目标目录 Thread.currentThread().getContextClassLoader().getResource("").getPath()当前工程目录路径
//String targetPDFPath = URLDecoder.decode(Demo3.class.getClassLoader().getResource("resources").getPath() + File.separator + "output.pdf", "UTF-8");
// String targetPDFPath = URLDecoder.decode(Main.class.getClassLoader().getResource("output.pdf").getFile(), "UTF-8");
String targetPDFPath = "F:\\00核心知识、成果、视频产出区\\技术视频\\2024.2.15 自制默默学打水印工具 watermark tools\\watermarkTools\\src\\main\\resources\\output.pdf";
File outputFile = new File(targetPDFPath);
// 若是文件存在先进行删除
Files.deleteIfExists(Paths.get(outputFile.toURI()));
// 保存修改后的文档
pdDocument.save(outputFile);
System.out.println("转换任务:" + targetPDFPath + " 成功!");
// 关闭文档
pdDocument.close(); // 关闭文档
}
}
效果:
https://img-blog.csdnimg.cn/img_convert/4b76c6ba38c8d17b8425004f7b1e4a49.png
demo4:添加居中45°笔墨水印
要求:对pdf每页都添加上旋转45°水印,透明度为20%。
https://img-blog.csdnimg.cn/img_convert/6ffb06f4912fd1c37d18499acb014f1e.png
package com.changlu.demos;
import com.changlu.Main;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDType0Font;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.apache.pdfbox.pdmodel.graphics.state.PDExtendedGraphicsState;
import java.io.File;
import java.io.InputStream;
import java.net.URLDecoder;
import java.nio.file.Files;
import java.nio.file.Paths;
/**
* @Description: Apache PDFBox案例:对pdf每页都添加上旋转45°水印。
* @Author: changlu
* @Date: 1:38 PM
*/
public class Demo4 {
public static void main(String[] args) throws Exception{
//读取resources目录下input.pdf文件
InputStream is = Main.class.getClassLoader().getResourceAsStream("input.pdf");
PDDocument pdDocument = PDDocument.load(is);
//自定义字体 C:\Users\93997\Desktop\watermark tools\watermarkTools\target\classes\ttfs
//URLDecoder.decode() 方法来解码 URL 编码的路径,将 %20 转换回空格
String fontFile = URLDecoder.decode(Main.class.getClassLoader().getResource(File.separator + "ttfs" + File.separator + "Alibaba_PuHuiTi_2.0_65_Medium_65_Medium.ttf").getFile(), "UTF-8");
PDType0Font font = PDType0Font.load(pdDocument, new File(fontFile));
// 设置透明度状态对象
PDExtendedGraphicsState graphicsState = new PDExtendedGraphicsState();
graphicsState.setNonStrokingAlphaConstant(0.2f);
graphicsState.setAlphaSourceFlag(true);
graphicsState.setStrokingAlphaConstant(0.2f);
//设置水印名
String waterText = "江苏专转本网课报名vx:mmxchanglu";
//遍历原先的pdf文档
for (PDPage page : pdDocument.getPages()) {
float pageWidth = page.getMediaBox().getWidth();
float pageHeight = page.getMediaBox().getHeight();
//添加水印 要求:旋转45°,不透明度30%
float waterTextWidth = font.getStringWidth(waterText) / 1000 * 30;
float waterCenteredX = (pageWidth - waterTextWidth) / 2;
float waterCenteredY = pageHeight / 2;
//创建一个水印内容流
PDPageContentStream waterContentStream = new PDPageContentStream(pdDocument, page, PDPageContentStream.AppendMode.APPEND, true, true);
waterContentStream.beginText();
waterContentStream.setFont(font, 30);
// 设置不透明度
waterContentStream.setNonStrokingColor(0, 0, 0); // black color
waterContentStream.setStrokingColor(0, 0, 0); // black color
waterContentStream.setGraphicsStateParameters(graphicsState);//设置透明度
//设置旋转文本 45° 对于tx、ty是以左下角为偏移位置中心来进行旋转角度
waterContentStream.setTextRotation(Math.toRadians(45), 400, -50);
//设置文本
waterContentStream.newLineAtOffset(waterCenteredX, waterCenteredY);
waterContentStream.showText(waterText);
waterContentStream.endText();
waterContentStream.close();
}
//目标目录 Thread.currentThread().getContextClassLoader().getResource("").getPath()当前工程目录路径
String targetPDFPath = "F:\\00核心知识、成果、视频产出区\\技术视频\\2024.2.15 自制默默学打水印工具 watermark tools\\watermarkTools\\src\\main\\resources\\output.pdf";
File outputFile = new File(targetPDFPath);
// 若是文件存在先进行删除
Files.deleteIfExists(Paths.get(outputFile.toURI()));
// 保存修改后的文档
pdDocument.save(outputFile);
System.out.println("转换任务:" + targetPDFPath + " 成功!");
// 关闭文档
pdDocument.close(); // 关闭文档
}
}
效果:
https://img-blog.csdnimg.cn/img_convert/b2a2a95894797084baac24438a738a9f.png
demo5:添加图片到右上角
要求:将图片缩小25%后插入到右上角。
https://img-blog.csdnimg.cn/img_convert/20f3160525a70ecd7db2a4f7a01b40e7.png
package com.changlu.demos;
import com.changlu.Main;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDType0Font;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.apache.pdfbox.pdmodel.graphics.state.PDExtendedGraphicsState;
import java.io.File;
import java.io.InputStream;
import java.net.URLDecoder;
import java.nio.file.Files;
import java.nio.file.Paths;
/**
* @Description: Apache PDFBox案例:将图片缩小25%后插入到右上角。
* @Author: changlu
* @Date: 1:38 PM
*/
public class Demo5 {
public static void main(String[] args) throws Exception{
//读取resources目录下input.pdf文件
InputStream is = Main.class.getClassLoader().getResourceAsStream("input.pdf");
PDDocument pdDocument = PDDocument.load(is);
//自定义字体 C:\Users\93997\Desktop\watermark tools\watermarkTools\target\classes\ttfs
//URLDecoder.decode() 方法来解码 URL 编码的路径,将 %20 转换回空格
String fontFile = URLDecoder.decode(Main.class.getClassLoader().getResource(File.separator + "ttfs" + File.separator + "Alibaba_PuHuiTi_2.0_65_Medium_65_Medium.ttf").getFile(), "UTF-8");
PDType0Font font = PDType0Font.load(pdDocument, new File(fontFile));
//遍历原先的pdf文档
for (PDPage page : pdDocument.getPages()) {
float pageWidth = page.getMediaBox().getWidth();
float pageHeight = page.getMediaBox().getHeight();
//添加图片水印
//创建一个水印内容流
PDPageContentStream imageContentStream = new PDPageContentStream(pdDocument, page, PDPageContentStream.AppendMode.APPEND, true, true);
// 创建图像对象
// PDImageXObject image = PDImageXObject.createFromFile("C:\\Users\\93997\\Desktop\\watermark tools\\watermarkTools\\src\\main\\resources\\images\\ConsultationGroupQRCode.jpg", pdDocument);
String pictureFile = URLDecoder.decode(Main.class.getClassLoader().getResource(File.separator + "images" + File.separator + "ConsultationGroupQRCode.jpg").getFile(), "UTF-8");
PDImageXObject image = PDImageXObject.createFromFile(pictureFile, pdDocument);
// 计算图像的宽度和高度(缩小比例为0.3)
float imageWidth = (float) (image.getWidth() * 0.25);
float imageHeight = (float) (image.getHeight() * 0.25);
//具体图片位置
float imageX = pageWidth - imageWidth - 10;
float imageY = pageHeight - imageHeight - 10;
// 在指定位置绘制图像
imageContentStream.drawImage(image, imageX, imageY, imageWidth, imageHeight);
imageContentStream.close();
}
//目标目录 Thread.currentThread().getContextClassLoader().getResource("").getPath()当前工程目录路径
String targetPDFPath = "F:\\00核心知识、成果、视频产出区\\技术视频\\2024.2.15 自制默默学打水印工具 watermark tools\\watermarkTools\\src\\main\\resources\\output.pdf";
File outputFile = new File(targetPDFPath);
// 若是文件存在先进行删除
Files.deleteIfExists(Paths.get(outputFile.toURI()));
// 保存修改后的文档
pdDocument.save(outputFile);
System.out.println("转换任务:" + targetPDFPath + " 成功!");
// 关闭文档
pdDocument.close(); // 关闭文档
}
}
效果:
https://img-blog.csdnimg.cn/img_convert/c8146d9160d1734574eccd1be0cf9a66.png
参考文章
. 使用 Apache PDFBox 操作PDF文件
. Java使用pdfbox将已有的pdf添加页眉
. 基于pdfbox实现的pdf添加笔墨水印工具
资料获取
大家点赞、收藏、关注、评论啦~
精彩专栏保举订阅:在下方专栏
页:
[1]