开源PDF工具 Apache PDFBox 认识及使用(知识点+案例)

长路 ㅤ    2024-06-16 12:37:24 阅读 52

文章目录

前言源码获取一、认识PDFBox二、导入依赖三、基础功能demo1:读取pdf所有内容demo2:读取所有页内容(分页)demo3:添加页眉、页脚demo4:添加居中45°文字水印demo5:添加图片到右上角 参考文章资料获取

前言

博主介绍:✌目前全网粉丝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所有内容

image-20240215133728958

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); }}

image-20240214114352374


demo2:读取所有页内容(分页)

image-20240215133844340

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); } }}

image-20240214114934921


demo3:添加页眉、页脚

要求:页眉页脚居中显示。

image-20240215140356576

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(); // 关闭文档 }}

效果:

image-20240215140103828


demo4:添加居中45°文字水印

要求:对pdf每页都添加上旋转45°水印,透明度为20%。

image-20240215141008094

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(); // 关闭文档 }}

效果:

image-20240215140939521


demo5:添加图片到右上角

要求:将图片缩小25%后插入到右上角。

image-20240215141247658

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(); // 关闭文档 }}

效果:

image-20240215141201348


参考文章

[1]. 使用 Apache PDFBox 操作PDF文件

[2]. Java使用pdfbox将已有的pdf添加页眉

[3]. 基于pdfbox实现的pdf添加文字水印工具


资料获取

大家点赞、收藏、关注、评论啦~

精彩专栏推荐订阅:在下方专栏👇🏻

长路-文章目录汇总(算法、后端Java、前端、运维技术导航):博主所有博客导航索引汇总开源项目Studio-Vue—校园工作室管理系统(含前后台,SpringBoot+Vue):博主个人独立项目,包含详细部署上线视频,已开源学习与生活-专栏:可以了解博主的学习历程算法专栏:算法收录

更多博客与资料可查看👇🏻获取联系方式👇🏻,🍅文末获取开发资源及更多资源博客获取🍅



声明

本文内容仅代表作者观点,或转载于其他网站,本站不以此文作为商业用途
如有涉及侵权,请联系本站进行删除
转载本站原创文章,请注明来源及作者。