写点什么

五分钟实现 pdf 分页

  • 2023-02-11
    北京
  • 本文字数:2803 字

    阅读完需:约 9 分钟

五分钟实现pdf分页

背景

抱歉也开始用了这么“标题党”的标题。事情起源于前几天需要把个人资料的 pdf 文档一页一页的拆出来,好传到相关的网站上。直接截图到 word 再转 pdf 比较麻烦,所以想用工具直接转换。结果找了几个 pdf 阅读器,这类操作都需要会员或收费。作为一名程序员,这么简单的操作还要收费显然是一种羞耻(当然我是不会承认主要是因为 qiong 的),几分钟就可以代码解决的问题为啥要花钱呢?废话不多说,开搞。

工具准备

之前的文章Apache POI 详解及 Word 文档读取示例中,我们曾经用 apache poi 来实现对 word 文档的操作。对于 pdf 文件,也同样有 apache 的 pdfbox(官网:https://pdfbox.apache.org/),和 itextpdf(官网:https://itextpdf.com/)包可以使用。

PDFBox:

PDFBox 是 Java 实现的 PDF 文档协作类库,提供 PDF 文档的创建、处理以及文档内容提取功能,也包含了一些命令行实用工具。PDFBox 提供的主要功能有:

  • 从 PDF 提取文本

  • 合并 PDF 文档

  • PDF 文档加密与解密

  • 与 Lucene 搜索引擎的集成

  • 填充 PDF/XFDF 表单数据

  • 从文本文件创建 PDF 文档

  • 从 PDF 页面创 建图片

  • 打印 PDF 文档

itextpdf:

iText 是著名的开放源码的站点 sourceforge 一个项目,是用于生成 PDF 文档的一个 java 类库。通过 iText 不仅可以生成 PDF 或 rtf 的文档,而且可以将 XML、Html 文件转化为 PDF 文件。 iText 的安装非常方便,下载 iText.jar 文件后,只需要在系统的 CLASSPATH 中加入 iText.jar 的路径,在程序中就可以使用 iText 类库了。

依赖引入

新建一个 java maven 工程,引入依赖包(这里使用的是 itextpdf 的 5.5.1 和 pdfbox 的 2.0.15 版本):

<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0"         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">    <modelVersion>4.0.0</modelVersion>
<groupId>org.example</groupId> <artifactId>pdf-test</artifactId> <version>1.0-SNAPSHOT</version>
<dependencies> <dependency> <groupId>com.itextpdf</groupId> <artifactId>itextpdf</artifactId> <version>5.5.1</version> <type>jar</type> </dependency>
<dependency> <groupId>org.apache.pdfbox</groupId> <artifactId>pdfbox</artifactId> <version>2.0.15</version> </dependency>
<!-- https://mvnrepository.com/artifact/org.apache.pdfbox/fontbox --> <dependency> <groupId>org.apache.pdfbox</groupId> <artifactId>fontbox</artifactId> <version>2.0.15</version> </dependency> <!-- https://mvnrepository.com/artifact/org.apache.pdfbox/jempbox --> <dependency> <groupId>org.apache.pdfbox</groupId> <artifactId>jempbox</artifactId> <version>1.8.16</version> </dependency> </dependencies>
</project>
复制代码

pdf 文件拆分导出实现

要实现功能:输入 pdf 文件路径,指定起止页码,截取这几页内容并写入新的 pdf 文件。例如起始页码 1,截止页码 3,则生成一个新文件,存储原 pdf 文档的 1-3 页。

这里使用的是 itextpdf,代码如下:

/**	 * 导出pdf文档中的部分页到新的pdf文件	 * @param filePath 文件路径	 * @param newFile 写入目标文件路径	 * @param from 起始页码	 * @param end 结束页码	 */	public static void pdfToSub(String filePath, String newFile, int from, int end) {		Document document = null;		PdfCopy copy = null;		try {			PdfReader reader = new PdfReader(filePath);			//查询pdf文档页数			int n = reader.getNumberOfPages();			if (end == 0) {				end = n;			}			document = new Document(reader.getPageSize(1));			copy = new PdfCopy(document, new FileOutputStream(newFile));			document.open();			for (int j = from; j <= end; j++) {				document.newPage();				PdfImportedPage page = copy.getImportedPage(reader, j);				copy.addPage(page);			}			document.close();		} catch (Exception e) {			e.printStackTrace();		}	}
复制代码

main 函数:

String filePath = "/Users/xxxx/Downloads/数据中台- 77ebooks.com.pdf";String newFile = "/Users/xxxx/Downloads/1-3.pdf";pdfToSub(filePath, newFile, 1, 3);
复制代码

执行后在目录下可以看到结果文件:


读取 pdf 文件内容

使用 pdfbox 的 pdfparser,代码如下:

/**	 * 读取pdf文档指定页数的文本内容	 * @param fileName 文件路径及文件名	 * @param from 开始页码	 * @param end 结束页码	 * @return	 */	public static String readPdfByPage(String fileName, int from, int end) {		String result = "";		File file = new File(fileName);		FileInputStream in = null;		try {			in = new FileInputStream(fileName);			// 新建PDF解析器对象			PDFParser parser = new PDFParser(new RandomAccessFile(file,"rw"));			// 文件解析			parser.parse();			// 获取解析后得到的PDF文档对象			PDDocument pdfDocument = parser.getPDDocument();			int size = pdfDocument.getNumberOfPages();			// 新建PDF文本剥离器			PDFTextStripper stripper = new PDFTextStripper();			stripper.setSortByPosition(false); //true则按照行进行读取,默认false
// 设置起始页 stripper.setStartPage(from); // 设置结束页 stripper.setEndPage(end); // 从PDF文档中读取文本 result = stripper.getText(pdfDocument); } catch (Exception e) { e.printStackTrace(); } finally { if (in != null) { try { in.close(); } catch (IOException e1) { e1.printStackTrace(); } } } return result; }
复制代码

执行后输出:

示例需要需要引入的 package 如下:

import com.itextpdf.text.Document;import com.itextpdf.text.pdf.PdfCopy;import com.itextpdf.text.pdf.PdfImportedPage;import com.itextpdf.text.pdf.PdfReader;import org.apache.pdfbox.io.RandomAccessFile;import org.apache.pdfbox.pdfparser.PDFParser;import org.apache.pdfbox.pdmodel.PDDocument;import org.apache.pdfbox.text.PDFTextStripper;
import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.IOException;
复制代码

小结

本篇对 pdf 的操作做了初步的尝试。后续将详解 pdf 文件格式,以及 pdfbox 和 itextpdf 的核心源码。

发布于: 刚刚阅读数: 4
用户头像

磨炼中成长,痛苦中前行 2017-10-22 加入

微信公众号【程序员架构进阶】。多年项目实践,架构设计经验。曲折中向前,分享经验和教训

评论

发布
暂无评论
五分钟实现pdf分页_PDF_程序员架构进阶_InfoQ写作社区