1. 简介
本文将深入探讨Java中PDF文件与其他格式之间的程序化转换。我们将重点介绍如何使用多个Java开源库实现以下功能:
- 将PDF保存为PNG/JPEG等图像文件
- 转换PDF为Microsoft Word文档
- 导出为HTML格式
- 提取PDF文本内容
⚠️ 注意:PDF转换并非100%精确,结果取决于源文件的复杂度和结构
2. Maven依赖
2.1 核心转换库
首先需要添加以下Maven依赖:
<dependency>
<groupId>org.apache.pdfbox</groupId>
<artifactId>pdfbox-tools</artifactId>
<version>3.0.0</version>
</dependency>
<dependency>
<groupId>net.sf.cssbox</groupId>
<artifactId>pdf2dom</artifactId>
<version>2.0.1</version>
</dependency>
pdfbox-tools
:用于加载PDF文件pdf2dom
:负责核心转换功能
2.2 文本处理库
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.5.10</version>
</dependency>
<dependency>
<groupId>com.itextpdf.tool</groupId>
<artifactId>xmlworker</artifactId>
<version>5.5.10</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.15</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>3.15</version>
</dependency>
iText
:提取PDF文本POI
:创建.docx文档
3. PDF与HTML互转
3.1 PDF转HTML
使用Pdf2Dom库实现转换:
private void generateHTMLFromPDF(String filename) {
PDDocument pdf = PDDocument.load(new File(filename));
Writer output = new PrintWriter("src/output/pdf.html", "utf-8");
new PDFDomTree().writeText(pdf, output);
output.close();
}
关键步骤:
- 使用PDFBox加载PDF文件
- 通过PDFDomTree解析并写入HTML
- 确保关闭输出流
❌ 踩坑提醒:PDF转HTML无法做到像素级完全一致
3.2 HTML转PDF
使用iText的XMLWorker实现:
private static void generatePDFFromHTML(String filename) {
Document document = new Document();
PdfWriter writer = PdfWriter.getInstance(document,
new FileOutputStream("src/output/html.pdf"));
document.open();
XMLWorkerHelper.getInstance().parseXHtml(writer, document,
new FileInputStream(filename));
document.close();
}
⚠️ 注意事项:
- HTML标签必须严格闭合
- 转换结果与HTML显示效果高度一致
4. PDF与图像互转
4.1 PDF转图像
使用Apache PDFBox实现:
private void generateImageFromPDF(String filename, String extension) {
PDDocument document = PDDocument.load(new File(filename));
PDFRenderer pdfRenderer = new PDFRenderer(document);
for (int page = 0; page < document.getNumberOfPages(); ++page) {
BufferedImage bim = pdfRenderer.renderImageWithDPI(
page, 300, ImageType.RGB);
ImageIOUtil.writeImage(
bim, String.format("src/output/pdf-%d.%s", page + 1, extension), 300);
}
document.close();
}
核心要点:
- 每页PDF需单独渲染
- 支持格式:jpeg/jpg/gif/tiff/png
- 可设置DPI(示例中为300)
✅ 优势:PDFBox功能强大,支持创建/签名/加密PDF
4.2 图像转PDF
使用iText实现:
private static void generatePDFFromImage(String filename, String extension) {
Document document = new Document();
String input = filename + "." + extension;
String output = "src/output/" + extension + ".pdf";
FileOutputStream fos = new FileOutputStream(output);
PdfWriter writer = PdfWriter.getInstance(document, fos);
writer.open();
document.open();
document.add(Image.getInstance((new URL(input))));
document.close();
writer.close();
}
支持场景:
- 本地文件路径
- 网络URL(如示例所示)
- 多种图像格式
5. PDF与文本互转
5.1 PDF转文本
使用Apache PDFBox提取文本:
File f = new File(filename);
String parsedText;
PDFParser parser = new PDFParser(new RandomAccessFile(f, "r"));
parser.parse();
COSDocument cosDoc = parser.getDocument();
PDFTextStripper pdfStripper = new PDFTextStripper();
PDDocument pdDoc = new PDDocument(cosDoc);
parsedText = pdfStripper.getText(pdDoc);
PrintWriter pw = new PrintWriter("src/output/pdf.txt");
pw.print(parsedText);
pw.close();
处理流程:
- 以只读模式解析PDF
- 使用PDFTextStripper提取文本
- 保存为纯文本文件
❌ 限制:纯文本无法保留原始格式
5.2 文本转PDF
使用iText实现转换:
Document pdfDoc = new Document(PageSize.A4);
PdfWriter.getInstance(pdfDoc, new FileOutputStream("src/output/txt.pdf"))
.setPdfVersion(PdfWriter.PDF_VERSION_1_7);
pdfDoc.open();
Font myfont = new Font();
myfont.setStyle(Font.NORMAL);
myfont.setSize(11);
pdfDoc.add(new Paragraph("\n"));
BufferedReader br = new BufferedReader(new FileReader(filename));
String strLine;
while ((strLine = br.readLine()) != null) {
Paragraph para = new Paragraph(strLine + "\n", myfont);
para.setAlignment(Element.ALIGN_JUSTIFIED);
pdfDoc.add(para);
}
pdfDoc.close();
br.close();
关键配置:
- 设置A4纸张和PDF版本
- 自定义字体样式
- 按行读取并添加段落
⚠️ 注意:简单实现会丢失原始文本格式
6. PDF转Docx
结合iText和POI实现:
XWPFDocument doc = new XWPFDocument();
String pdf = filename;
PdfReader reader = new PdfReader(pdf);
PdfReaderContentParser parser = new PdfReaderContentParser(reader);
for (int i = 1; i <= reader.getNumberOfPages(); i++) {
TextExtractionStrategy strategy =
parser.processContent(i, new SimpleTextExtractionStrategy());
String text = strategy.getResultantText();
XWPFParagraph p = doc.createParagraph();
XWPFRun run = p.createRun();
run.setText(text);
run.addBreak(BreakType.PAGE);
}
FileOutputStream out = new FileOutputStream("src/output/pdf.docx");
doc.write(out);
实现原理:
- 使用iText提取每页文本
- 通过POI创建Word段落
- 添加分页符保持页面结构
❌ 缺陷:SimpleTextExtractionStrategy会丢失所有格式
7. 商业PDF转换库
以下付费库提供更专业的解决方案:
库名称 | 主要功能 | 特点 |
---|---|---|
jPDFImages | PDF转图像 | 支持JPEG/TIFF/PNG导出 |
JPEDAL | PDF处理套件 | 原生Java SDK,支持打印/查看/转换 |
pdfcrowd | Web/HTML转换 | 提供高级GUI界面 |
8. Docx转PDF
使用POI读取Word,iText生成PDF:
InputStream docxInputStream = new FileInputStream("input.docx");
try (XWPFDocument document = new XWPFDocument(docxInputStream);
OutputStream pdfOutputStream = new FileOutputStream("output.pdf");) {
Document pdfDocument = new Document();
PdfWriter.getInstance(pdfDocument, pdfOutputStream);
pdfDocument.open();
List<XWPFParagraph> paragraphs = document.getParagraphs();
for (XWPFParagraph paragraph : paragraphs) {
pdfDocument.add(new Paragraph(paragraph.getText()));
}
pdfDocument.close();
}
处理流程:
- 使用XWPFDocument加载Docx
- 遍历所有段落
- 逐段写入PDF文档
9. 总结
本文系统介绍了Java中PDF与其他格式的转换方案:
✅ 核心技术栈:
- Apache PDFBox:PDF解析/图像转换
- iText:HTML/文本处理
- POI:Office文档操作
⚠️ 关键注意事项:
- 转换精度受源文件结构影响
- 格式保留需要特殊处理
- 复杂场景建议使用商业库
完整示例代码可在GitHub仓库获取。