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

关键步骤:

  1. 使用PDFBox加载PDF文件
  2. 通过PDFDomTree解析并写入HTML
  3. 确保关闭输出流

❌ 踩坑提醒: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();

处理流程:

  1. 以只读模式解析PDF
  2. 使用PDFTextStripper提取文本
  3. 保存为纯文本文件

❌ 限制:纯文本无法保留原始格式

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

实现原理:

  1. 使用iText提取每页文本
  2. 通过POI创建Word段落
  3. 添加分页符保持页面结构

❌ 缺陷: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();
}

处理流程:

  1. 使用XWPFDocument加载Docx
  2. 遍历所有段落
  3. 逐段写入PDF文档

9. 总结

本文系统介绍了Java中PDF与其他格式的转换方案:

✅ 核心技术栈:

  • Apache PDFBox:PDF解析/图像转换
  • iText:HTML/文本处理
  • POI:Office文档操作

⚠️ 关键注意事项:

  1. 转换精度受源文件结构影响
  2. 格式保留需要特殊处理
  3. 复杂场景建议使用商业库

完整示例代码可在GitHub仓库获取。


原始标题:PDF Conversions in Java | Baeldung