文章目录

  • 使用Apache PDFBox实现拆分、合并PDF
    • 问题背景
    • Apache PDFBox介绍
    • 拆分PDF
    • 合并PDF
    • 拆分 + 合并
    • 完整代码
    • 参考:

使用Apache PDFBox实现拆分、合并PDF

问题背景

  • 如何拆分PDF?
  • 如何合并PDF?
  • 如何拆分合并PDF实现去除PDF的某些页?

Apache PDFBox介绍

Apache PDFBox 1.8.10官方文档

Apache PDFBox 库是一个开源的 Java 工具,用于处理 PDF 文件。该项目允许创建新的PDF文档,操作 现有文档以及从文档中提取内容的能力。 PDFBox还包括几个命令行实用程序。PDFBox 发布 在 Apache 许可证下,版本 2.0。

也就是说,我们可以使用PDFBox实现拆分合并PDF。

在maven项目中添加依赖:

        <!--PDF操作--><dependency><groupId>org.apache.pdfbox</groupId><artifactId>pdfbox-app</artifactId><version>1.8.10</version></dependency>

拆分PDF

我们需实现WPS这种按照范围拆分的拆分规则:

  1. 参考样例

以下是wiki教程中找到的样例,可以实现按照每页拆分成pdf。

public static void main(String[] args) throws IOException {//Loading an existing PDF documentFile file = new File("C:/PdfBox_Examples/sample.pdf");PDDocument document = PDDocument.load(file); //Instantiating Splitter classSplitter splitter = new Splitter();//splitting the pages of a PDF documentList<PDDocument> Pages = splitter.split(document);//Creating an iterator Iterator<PDDocument> iterator = Pages.listIterator();//Saving each page as an individual documentint i = 1;while(iterator.hasNext()) {PDDocument pd = iterator.next();pd.save("C:/PdfBox_Examples/sample"+ i++ +".pdf");}System.out.println("Multiple PDF’s created");document.close();}
  1. org.apache.pdfbox.util.Splitter

Splitter 类有三个拆分相关的参数

    private int splitAtPage = 1;private int startPage = -2147483648;private int endPage = 2147483647;

分别代表拆分的页数范围,开始拆分的页数,结束拆分的页数。

也就是说,我们可以通过实现设置splitter的相关参数(如splitter.setStartPage(12)等)来实现按照范围拆分的功能。

  1. 匹配拆分规则

建立SplitterDTO

/*** Splitter类的配置*/
@Data
class SplitterDTO {private int splitAtPage;private int startPage;private int endPage;
}

使用正则表达式校验按照范围拆分的拆分规则,将其参数保存在List<SplitterDTO>中:

    // m-n 例如 3-5,拆分第三到第五页的pdfprivate static final String ruleOne = "^[1-9]\\d*-[1-9]\\d*$";// m 例如 7,拆分第七页的pdfprivate static final String ruleTwo = "^[1-9]\\d*$";/*** 正则校验匹配  拆分规则* @param splitRule 拆分规则* @return*/private List<SplitterDTO> matchByRegex(String splitRule) {List<SplitterDTO> result = new ArrayList<>();String[] splits = splitRule.split(",");for (String split : splits) {SplitterDTO dto = new SplitterDTO();if (split.matches(ruleOne)) {String[] nums = split.split("-");dto.setStartPage(Integer.parseInt(nums[0]));dto.setEndPage(Integer.parseInt(nums[1]));// 拆分的长度dto.setSplitAtPage(dto.getEndPage() - dto.getStartPage() + 1);result.add(dto);} else if (split.matches(ruleTwo)) {dto.setStartPage(Integer.parseInt(split));dto.setEndPage(Integer.parseInt(split));dto.setSplitAtPage(1);result.add(dto);} else {System.out.println("错误的规则:" + split);}}return result;}
  1. 拆分PDF

根据拆分规则开始拆分PDF并保存为pdf。

    /*** 拆分pdf* @param sourcePdf 源pdf(路径+文件名+文件后缀)* @param splitPath 拆分后的文件路径* @param splitFileName 拆分后的文件名(不含后缀)* @param splitterDTOS 拆分规则* @return finalPdfs 最终拆分成的pdf*/private List<String> spitPdf(String sourcePdf, String splitPath, String splitFileName, List<SplitterDTO> splitterDTOS) throws IOException, COSVisitorException {List<String> finalPdfs = new ArrayList<>();int j = 1;String splitPdf = splitPath + "\\" + splitFileName + "_";for (SplitterDTO splitterDTO : splitterDTOS) {// Loading an existing PDF documentFile file = new File(sourcePdf);PDDocument document = PDDocument.load(file);// Instantiating Splitter classSplitter splitter = new Splitter();splitter.setStartPage(splitterDTO.getStartPage());splitter.setSplitAtPage(splitterDTO.getSplitAtPage());splitter.setEndPage(splitterDTO.getEndPage());// splitting the pages of a PDF documentList<PDDocument> Pages = splitter.split(document);// Creating an iteratorIterator<PDDocument> iterator = Pages.listIterator();// Saving each page as an individual documentwhile(iterator.hasNext()) {PDDocument pd = iterator.next();String pdfName = splitPdf+ j++ +".pdf";pd.save(pdfName);finalPdfs.add(pdfName);}
//            System.out.println("Multiple PDF’s created");document.close();}return finalPdfs;}
  1. 拆分测试
    public static void main(String[] args) throws Exception {// 拆分规则:如拆分成1-4,5,以及8三个pdfString splitRule = "1-4,5,8";String sourcePdf = "D:\\BaiduNetdiskDownload\\test\\测试用pdf.pdf";// 拆分后pdf所放的文件夹String splitPath = "D:\\BaiduNetdiskDownload\\test";// 拆分后的文件名String splitFileName = UUID.randomUUID().toString().replace("-", "");/*** 1、拆分*/PdfUtils pdfUtils = new PdfUtils();List<SplitterDTO> splitterDTOS = pdfUtils.matchByRegex(splitRule);List<String> pdfList = pdfUtils.spitPdf(sourcePdf, splitPath, splitFileName, splitterDTOS);System.out.println("pdf文件拆分成功------------");pdfList.forEach(System.out::println);}

控制台输出结果:

pdf文件拆分成功------------
D:\BaiduNetdiskDownload\test\a5f1b001f2d64a75ac63e75bdb4809e6_1.pdf
D:\BaiduNetdiskDownload\test\a5f1b001f2d64a75ac63e75bdb4809e6_2.pdf
D:\BaiduNetdiskDownload\test\a5f1b001f2d64a75ac63e75bdb4809e6_3.pdf

对应文件夹生成三个pdf文件:


合并PDF

  1. 代码
    /*** 合并PDF* @param inputStreams 需合并的pdf文件流* @param bothPath 合并后的pdf文件路径* @param destinationFileName 合并后的pdf文件名*/public static void MergePdf(List<InputStream> inputStreams, String bothPath, String destinationFileName) throws Exception {// org.apache.pdfbox.util.PDFMergerUtility:pdf合并工具类PDFMergerUtility mergePdf = new PDFMergerUtility();File file = new File(bothPath);if (!file.exists()) {file.mkdirs();}mergePdf.addSources(inputStreams);// 设置合并生成pdf文件名称mergePdf.setDestinationFileName(bothPath + File.separator + destinationFileName);// 合并PDFmergePdf.mergeDocuments();for (InputStream in : inputStreams) {if (in != null) {in.close();}}}
  1. 合并测试
    public static void main(String[] args) throws Exception {/*** 合并*/// 合并pdf生成的文件名String destinationFileName = DateUtils.format(new Date());// 需要合并的PDF文件List<InputStream> inputStreams = new ArrayList<>();inputStreams.add(new FileInputStream(new File("D:\\ToPDF\\pdf\\水印冲鸭.pdf")));inputStreams.add(new FileInputStream(new File("D:\\ToPDF\\pdf\\testtest.pdf")));// 合并后pdf存放路径String bothPath = "D:\\ToPDF\\pdf";MergePdf(inputStreams, bothPath, destinationFileName+"测试合并.pdf");System.out.println("pdf文件合并成功");}

控制台输出结果:

pdf文件合并成功

对应文件夹生成合并的pdf文件:


拆分 + 合并

  1. 测试代码
    public static void main(String[] args) throws Exception {// 拆分规则:如拆分成1-4,5,以及8三个pdfString splitRule = "1-4,5,8";String sourcePdf = "D:\\BaiduNetdiskDownload\\test\\测试用pdf.pdf";// 拆分后pdf所放的文件夹String splitPath = "D:\\BaiduNetdiskDownload\\test";// 拆分后的文件名String splitFileName = UUID.randomUUID().toString().replace("-", "");/*** 1、拆分*/PdfUtils pdfUtils = new PdfUtils();List<SplitterDTO> splitterDTOS = pdfUtils.matchByRegex(splitRule);List<String> pdfList = pdfUtils.spitPdf(sourcePdf, splitPath, splitFileName, splitterDTOS);System.out.println("pdf文件拆分成功------------");pdfList.forEach(System.out::println);/*** 2、合并*/// 合并pdf生成的文件名String destinationFileName = splitFileName;// 需要合并的PDF文件List<InputStream> inputStreams = new ArrayList<>();for (String pdf : pdfList) {inputStreams.add(new FileInputStream(new File(pdf)));}// 合并后pdf存放路径String bothPath = "D:\\BaiduNetdiskDownload\\test";MergePdf(inputStreams, bothPath, destinationFileName + "测试合并.pdf");System.out.println("pdf文件合并成功-----------");}
  1. 测试结果
    控制台输出结果:
pdf文件拆分成功------------
D:\BaiduNetdiskDownload\test\a5f1b001f2d64a75ac63e75bdb4809e6_1.pdf
D:\BaiduNetdiskDownload\test\a5f1b001f2d64a75ac63e75bdb4809e6_2.pdf
D:\BaiduNetdiskDownload\test\a5f1b001f2d64a75ac63e75bdb4809e6_3.pdf
pdf文件合并成功-----------

对应文件夹生成拆分后以及合并的pdf文件:


完整代码

package com.example.demo.utils;import lombok.Data;
import org.apache.pdfbox.exceptions.COSVisitorException;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.util.PDFMergerUtility;
import org.apache.pdfbox.util.Splitter;import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;/*** @Author 似有风中泣* @Description 操作PDF类* @Data 2022/6/27 16:18* @Version 1.0*/
public class PdfUtils {// m-n 例如 3-5,拆分第三到第五页的pdfprivate static final String ruleOne = "^[1-9]\\d*-[1-9]\\d*$";// m 例如 7,拆分第七页的pdfprivate static final String ruleTwo = "^[1-9]\\d*$";public static void main(String[] args) throws Exception {// 拆分规则:如拆分成1-4,5,以及8三个pdfString splitRule = "1-4,5,8";String sourcePdf = "D:\\BaiduNetdiskDownload\\test\\测试用pdf.pdf";// 拆分后pdf所放的文件夹String splitPath = "D:\\BaiduNetdiskDownload\\test";// 拆分后的文件名String splitFileName = UUID.randomUUID().toString().replace("-", "");/*** 1、拆分*/PdfUtils pdfUtils = new PdfUtils();List<SplitterDTO> splitterDTOS = pdfUtils.matchByRegex(splitRule);List<String> pdfList = pdfUtils.spitPdf(sourcePdf, splitPath, splitFileName, splitterDTOS);System.out.println("pdf文件拆分成功------------");pdfList.forEach(System.out::println);/*** 2、合并*/// 合并pdf生成的文件名String destinationFileName = splitFileName;// 需要合并的PDF文件List<InputStream> inputStreams = new ArrayList<>();for (String pdf : pdfList) {inputStreams.add(new FileInputStream(new File(pdf)));}// 合并后pdf存放路径String bothPath = "D:\\BaiduNetdiskDownload\\test";MergePdf(inputStreams, bothPath, destinationFileName + "测试合并.pdf");System.out.println("pdf文件合并成功-----------");}/*** 正则校验匹配  拆分规则* @param splitRule 拆分规则* @return*/private List<SplitterDTO> matchByRegex(String splitRule) {List<SplitterDTO> result = new ArrayList<>();String[] splits = splitRule.split(",");for (String split : splits) {SplitterDTO dto = new SplitterDTO();if (split.matches(ruleOne)) {String[] nums = split.split("-");dto.setStartPage(Integer.parseInt(nums[0]));dto.setEndPage(Integer.parseInt(nums[1]));// 拆分的长度dto.setSplitAtPage(dto.getEndPage() - dto.getStartPage() + 1);result.add(dto);} else if (split.matches(ruleTwo)) {dto.setStartPage(Integer.parseInt(split));dto.setEndPage(Integer.parseInt(split));dto.setSplitAtPage(1);result.add(dto);} else {System.out.println("错误的规则:" + split);}}return result;}/*** 拆分pdf* @param sourcePdf 源pdf(路径+文件名+文件后缀)* @param splitPath 拆分后的文件路径* @param splitFileName 拆分后的文件名(不含后缀)* @param splitterDTOS 拆分规则* @return finalPdfs 最终拆分成的pdf*/private List<String> spitPdf(String sourcePdf, String splitPath, String splitFileName, List<SplitterDTO> splitterDTOS) throws IOException, COSVisitorException {List<String> finalPdfs = new ArrayList<>();int j = 1;String splitPdf = splitPath + "\\" + splitFileName + "_";for (SplitterDTO splitterDTO : splitterDTOS) {// Loading an existing PDF documentFile file = new File(sourcePdf);PDDocument document = PDDocument.load(file);// Instantiating Splitter classSplitter splitter = new Splitter();splitter.setStartPage(splitterDTO.getStartPage());splitter.setSplitAtPage(splitterDTO.getSplitAtPage());splitter.setEndPage(splitterDTO.getEndPage());// splitting the pages of a PDF documentList<PDDocument> Pages = splitter.split(document);// Creating an iteratorIterator<PDDocument> iterator = Pages.listIterator();// Saving each page as an individual documentwhile(iterator.hasNext()) {PDDocument pd = iterator.next();String pdfName = splitPdf+ j++ +".pdf";pd.save(pdfName);finalPdfs.add(pdfName);}
//            System.out.println("Multiple PDF’s created");document.close();}return finalPdfs;}/*** 合并PDF* @param inputStreams 需合并的pdf文件流* @param bothPath 合并后的pdf文件路径* @param destinationFileName 合并后的pdf文件名*/public static void MergePdf(List<InputStream> inputStreams, String bothPath, String destinationFileName) throws Exception {// pdf合并工具类PDFMergerUtility mergePdf = new PDFMergerUtility();File file = new File(bothPath);if (!file.exists()) {file.mkdirs();}mergePdf.addSources(inputStreams);// 设置合并生成pdf文件名称mergePdf.setDestinationFileName(bothPath + File.separator + destinationFileName);// 合并PDFmergePdf.mergeDocuments();for (InputStream in : inputStreams) {if (in != null) {in.close();}}}}/*** Splitter类的配置*/
@Data
class SplitterDTO {private int splitAtPage;private int startPage;private int endPage;
}

参考:

https://iowiki.com/pdfbox/pdfbox_splitting_a_pdf_document.html
https://github.com/apache/pdfbox
https://javadoc.io/doc/org.apache.pdfbox/pdfbox/1.8.10/index.html

使用Apache PDFBox实现拆分、合并PDF相关推荐

  1. Apache PDFbox开发指南之PDF文档读取

    转载请注明来源:http://blog.csdn.net/loongshawn/article/details/51542309 相关文章: <Apache PDFbox开发指南之PDF文本内容 ...

  2. 极速系列05—python批量拆分/合并PDF文档

    1 python按照页数拆分PDF文档 目的: 将一个PDF文档按照指定的页数拆份额为多个文档 思路: 使用PyPDF库中的PdfFileReader, PdfFileWriter类,这两个类是PyP ...

  3. adobe acrobat 拆分合并pdf

    1.拆分文件 0)左侧:页面缩略图->删除页面(删除你提取后剩余的页面,这样可以保留你留下部分的书签) 1)左侧:页面缩略图->提取页面(不要勾选提取页面为单独文件) 2)打印:使用ado ...

  4. 通过Apache PDFBox将pdf转换为word

    Apache PDFBox 库是一个开源.用于操作 PDF 文档的 Java 工具库.PDFBox 允许创建新的 PDF 文档.操作现有文档,以及从文档中提取内容. 获取 Apache PDFBox ...

  5. 使用 Apache PDFBox 操作PDF文件

    简介 Apache PDFBox库是一个用于处理PDF文档的开源Java工具.该项目允许创建新的PDF文档,操作现有PDF文档,并从PDF文档中提取内容.Apache PDFBox还包括几个命令行实用 ...

  6. Java工具类pdfbox将多个pdf合并成一个pdf。

    引入maven依赖: <!-- 将两个或多个单独的PDF文件合并成一个PDF文件--><dependency><groupId>org.apache.pdfbox& ...

  7. java pdfbox 合并PDF、PDF转图片、PDF插入图片

    1.添加依赖 <dependency><groupId>org.apache.pdfbox</groupId><artifactId>pdfbox< ...

  8. PDF文件拆分合并器PDF Merge PDF Splitter + Mac

    PDF Merge & PDF Splitter + Mac是专为Mac用户所提供的PDF文件拆分合并器,PDF Merge & PDF Splitter + Mac版能够为您将快速多 ...

  9. python处理pdf文件的程序_Python处理PDF文档-拆分合并

    使用Python处理PDF文档.将需要处理的PDF文档与处理程序放到一个新建的文件夹中.运行程序. S模式,将单个PDF文档拆分到单页,并以数字命名. image.png C模式,合并文档,需要提前将 ...

最新文章

  1. 芯片、模组、开发板的区别与联系-结合ESP32浅谈(转载)
  2. 《算法帝国》——华尔街,第一张多米诺骨牌
  3. python安装路径怎么找-Python---查看安装路径
  4. 鸟哥的Linux私房菜(基础篇)-第三章、主机规划与磁盘分区(三.4. 重点回顾)
  5. Android11.0 V-A/B无缝OTA升级update_engine
  6. Redis压力测试(详细)
  7. 如何让小孩练得一手好字?这5个小方法,家长不妨试试
  8. 外贸常用术语_外贸术语大全(超详细)
  9. java.io的缓冲流、转换流、序列化流
  10. win8系统中chm文件打不开怎么办
  11. FI-SAP财务成本知识点汇总
  12. mocha.opts配置文件
  13. 媒体访谈| 知道创宇邓金城: DDoS攻势愈烈,抗D服务需不断优化
  14. BZOJ3161 : 孤舟蓑笠翁
  15. 单自由度体系对简谐荷载的反应
  16. egret 龙骨操作,返回龙骨显示对象
  17. 关于C语言文件的读写
  18. 图像处理中的梯度、导数如何求?(Robert算子,Sobel算子,Prewitt算子,Laplace算子)
  19. 二手iPhone手机选购指南,花小钱办大事
  20. Chapter5 初始化(Initialization)

热门文章

  1. . xx.sh ./xx.sh sh xx.sh的区别
  2. 思科无线AP (AIR-AP1832I-K9)瘦ap 刷 胖ap
  3. 全数字OQPSK调制解调的基本算法,包括成形滤波器、NCO模型、载波恢复
  4. 加州伯克利计算机科学录取,加州大学伯克利分校录取数据分析
  5. 西方哲学史中49位哲学家的核心思想
  6. uniapp switch开关插件带文字/icon图标 功能实现
  7. 北京2008中国代表团名单
  8. 超大数相乘的java代码,java版大数相乘
  9. Python吴恩达深度学习作业16 -- 人脸识别
  10. python 爬虫 requests+BeautifulSoup 爬取巨潮资讯公司概况代码实例