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

2024-02-16 15:04

本文主要是介绍开源PDF工具 Apache PDFBox 认识及使用(知识点+案例),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • 前言
  • 源码获取
  • 一、认识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 colorwaterContentStream.setStrokingColor(0, 0, 0); // black colorwaterContentStream.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):博主个人独立项目,包含详细部署上线视频,已开源
  • 学习与生活-专栏:可以了解博主的学习历程
  • 算法专栏:算法收录

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

这篇关于开源PDF工具 Apache PDFBox 认识及使用(知识点+案例)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/714892

相关文章

使用Java将各种数据写入Excel表格的操作示例

《使用Java将各种数据写入Excel表格的操作示例》在数据处理与管理领域,Excel凭借其强大的功能和广泛的应用,成为了数据存储与展示的重要工具,在Java开发过程中,常常需要将不同类型的数据,本文... 目录前言安装免费Java库1. 写入文本、或数值到 Excel单元格2. 写入数组到 Excel表格

redis中使用lua脚本的原理与基本使用详解

《redis中使用lua脚本的原理与基本使用详解》在Redis中使用Lua脚本可以实现原子性操作、减少网络开销以及提高执行效率,下面小编就来和大家详细介绍一下在redis中使用lua脚本的原理... 目录Redis 执行 Lua 脚本的原理基本使用方法使用EVAL命令执行 Lua 脚本使用EVALSHA命令

Java 中的 @SneakyThrows 注解使用方法(简化异常处理的利与弊)

《Java中的@SneakyThrows注解使用方法(简化异常处理的利与弊)》为了简化异常处理,Lombok提供了一个强大的注解@SneakyThrows,本文将详细介绍@SneakyThro... 目录1. @SneakyThrows 简介 1.1 什么是 Lombok?2. @SneakyThrows

使用Python和Pyecharts创建交互式地图

《使用Python和Pyecharts创建交互式地图》在数据可视化领域,创建交互式地图是一种强大的方式,可以使受众能够以引人入胜且信息丰富的方式探索地理数据,下面我们看看如何使用Python和Pyec... 目录简介Pyecharts 简介创建上海地图代码说明运行结果总结简介在数据可视化领域,创建交互式地

Java中的工具类命名方法

《Java中的工具类命名方法》:本文主要介绍Java中的工具类究竟如何命名,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录Java中的工具类究竟如何命名?先来几个例子几种命名方式的比较到底如何命名 ?总结Java中的工具类究竟如何命名?先来几个例子JD

Java Stream流使用案例深入详解

《JavaStream流使用案例深入详解》:本文主要介绍JavaStream流使用案例详解,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录前言1. Lambda1.1 语法1.2 没参数只有一条语句或者多条语句1.3 一个参数只有一条语句或者多

Java Spring 中 @PostConstruct 注解使用原理及常见场景

《JavaSpring中@PostConstruct注解使用原理及常见场景》在JavaSpring中,@PostConstruct注解是一个非常实用的功能,它允许开发者在Spring容器完全初... 目录一、@PostConstruct 注解概述二、@PostConstruct 注解的基本使用2.1 基本代

C#使用StackExchange.Redis实现分布式锁的两种方式介绍

《C#使用StackExchange.Redis实现分布式锁的两种方式介绍》分布式锁在集群的架构中发挥着重要的作用,:本文主要介绍C#使用StackExchange.Redis实现分布式锁的... 目录自定义分布式锁获取锁释放锁自动续期StackExchange.Redis分布式锁获取锁释放锁自动续期分布式

springboot使用Scheduling实现动态增删启停定时任务教程

《springboot使用Scheduling实现动态增删启停定时任务教程》:本文主要介绍springboot使用Scheduling实现动态增删启停定时任务教程,具有很好的参考价值,希望对大家有... 目录1、配置定时任务需要的线程池2、创建ScheduledFuture的包装类3、注册定时任务,增加、删

使用Python实现矢量路径的压缩、解压与可视化

《使用Python实现矢量路径的压缩、解压与可视化》在图形设计和Web开发中,矢量路径数据的高效存储与传输至关重要,本文将通过一个Python示例,展示如何将复杂的矢量路径命令序列压缩为JSON格式,... 目录引言核心功能概述1. 路径命令解析2. 路径数据压缩3. 路径数据解压4. 可视化代码实现详解1