跳转至

Java 创建 PDF 文档:从入门到精通

简介

在当今数字化的时代,生成和处理 PDF 文档在许多应用场景中都至关重要,比如生成报告、合同、发票等。Java 作为一种广泛使用的编程语言,提供了多种方式来创建 PDF 文档。本文将深入探讨 Java 创建 PDF 文档的相关知识,包括基础概念、使用方法、常见实践以及最佳实践,帮助读者全面掌握这一技术。

目录

  1. 基础概念
  2. 使用方法
    • 使用 iText 库
    • 使用 Apache PDFBox
  3. 常见实践
    • 添加文本
    • 插入图像
    • 创建表格
  4. 最佳实践
    • 性能优化
    • 代码结构与维护
  5. 小结
  6. 参考资料

基础概念

PDF(Portable Document Format)是一种用于呈现文档的文件格式,它能够保留文档的原始格式、字体、图像等元素,独立于操作系统和应用程序。在 Java 中创建 PDF 文档,本质上是通过特定的库来生成符合 PDF 格式规范的文件。这些库提供了一系列的 API,允许开发者以编程的方式控制文档的内容、布局、样式等方面。

使用方法

使用 iText 库

iText 是一个广泛使用的 Java 库,用于创建、修改和提取 PDF 文档中的内容。

  1. 添加依赖 在 Maven 项目中,在 pom.xml 文件中添加以下依赖:
<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itextpdf</artifactId>
    <version>5.5.13</version>
</dependency>
  1. 创建简单 PDF 文档
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PdfWriter;

import java.io.FileOutputStream;
import java.io.IOException;

public class ITextExample {
    public static void main(String[] args) {
        Document document = new Document();
        try {
            PdfWriter.getInstance(document, new FileOutputStream("example.pdf"));
            document.open();
            document.add(new Paragraph("这是一个使用 iText 创建的 PDF 文档。"));
            document.close();
        } catch (DocumentException | IOException e) {
            e.printStackTrace();
        }
    }
}

使用 Apache PDFBox

Apache PDFBox 也是一个强大的 Java 库,用于处理 PDF 文档。

  1. 添加依赖 在 Maven 项目中,在 pom.xml 文件中添加以下依赖:
<dependency>
    <groupId>org.apache.pdfbox</groupId>
    <artifactId>pdfbox</artifactId>
    <version>2.0.23</version>
</dependency>
  1. 创建简单 PDF 文档
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDType1Font;

import java.io.IOException;

public class PDFBoxExample {
    public static void main(String[] args) {
        try (PDDocument document = new PDDocument()) {
            PDPage page = new PDPage();
            document.addPage(page);
            try (PDPageContentStream contentStream = new PDPageContentStream(document, page)) {
                contentStream.beginText();
                contentStream.setFont(PDType1Font.HELVETICA_BOLD, 12);
                contentStream.newLineAtOffset(100, 700);
                contentStream.showText("这是一个使用 Apache PDFBox 创建的 PDF 文档。");
                contentStream.endText();
            } catch (IOException e) {
                e.printStackTrace();
            }
            document.save("example.pdf");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

常见实践

添加文本

使用 iText

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Font;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PdfWriter;

import java.io.FileOutputStream;
import java.io.IOException;

public class ITextAddText {
    public static void main(String[] args) {
        Document document = new Document();
        try {
            PdfWriter.getInstance(document, new FileOutputStream("text_example.pdf"));
            document.open();
            Font font = new Font(Font.FontFamily.TIMES_ROMAN, 16, Font.BOLD);
            Paragraph paragraph = new Paragraph("这是一段加粗的文本", font);
            document.add(paragraph);
            document.close();
        } catch (DocumentException | IOException e) {
            e.printStackTrace();
        }
    }
}

使用 Apache PDFBox

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDType1Font;

import java.io.IOException;

public class PDFBoxAddText {
    public static void main(String[] args) {
        try (PDDocument document = new PDDocument()) {
            PDPage page = new PDPage();
            document.addPage(page);
            try (PDPageContentStream contentStream = new PDPageContentStream(document, page)) {
                contentStream.beginText();
                contentStream.setFont(PDType1Font.HELVETICA_BOLD, 16);
                contentStream.newLineAtOffset(100, 700);
                contentStream.showText("这是一段加粗的文本");
                contentStream.endText();
            } catch (IOException e) {
                e.printStackTrace();
            }
            document.save("text_example.pdf");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

插入图像

使用 iText

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.pdf.PdfWriter;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

public class ITextAddImage {
    public static void main(String[] args) {
        Document document = new Document();
        try {
            PdfWriter.getInstance(document, new FileOutputStream("image_example.pdf"));
            document.open();
            File imageFile = new File("logo.png");
            Image image = Image.getInstance(imageFile.getAbsolutePath());
            image.scaleToFit(200, 200);
            document.add(image);
            document.close();
        } catch (DocumentException | IOException e) {
            e.printStackTrace();
        }
    }
}

使用 Apache PDFBox

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;

import java.io.File;
import java.io.IOException;

public class PDFBoxAddImage {
    public static void main(String[] args) {
        try (PDDocument document = new PDDocument()) {
            PDPage page = new PDPage();
            document.addPage(page);
            PDImageXObject pdImage = PDImageXObject.createFromFile("logo.png", document);
            try (PDPageContentStream contentStream = new PDPageContentStream(document, page)) {
                contentStream.drawImage(pdImage, 100, 500, 200, 200);
            } catch (IOException e) {
                e.printStackTrace();
            }
            document.save("image_example.pdf");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

创建表格

使用 iText

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Table;
import com.itextpdf.text.pdf.PdfWriter;

import java.io.FileOutputStream;
import java.io.IOException;

public class ITextCreateTable {
    public static void main(String[] args) {
        Document document = new Document();
        try {
            PdfWriter.getInstance(document, new FileOutputStream("table_example.pdf"));
            document.open();
            Table table = new Table(3);
            table.addCell("表头 1");
            table.addCell("表头 2");
            table.addCell("表头 3");
            table.addCell("数据 1");
            table.addCell("数据 2");
            table.addCell("数据 3");
            document.add(table);
            document.close();
        } catch (DocumentException | IOException e) {
            e.printStackTrace();
        }
    }
}

使用 Apache PDFBox

import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.font.PDType1Font;

import java.io.IOException;

public class PDFBoxCreateTable {
    public static void main(String[] args) {
        try (PDDocument document = new PDDocument()) {
            PDPage page = new PDPage();
            document.addPage(page);
            try (PDPageContentStream contentStream = new PDPageContentStream(document, page)) {
                float[] columnWidths = {100, 100, 100};
                float tableX = 100;
                float tableY = 600;
                float tableWidth = 300;
                float tableHeight = 100;
                // 绘制表格边框
                contentStream.addRect(tableX, tableY, tableWidth, tableHeight);
                contentStream.stroke();
                // 绘制列分隔线
                for (int i = 1; i < columnWidths.length; i++) {
                    float x = tableX + columnWidths[i - 1];
                    contentStream.moveTo(x, tableY);
                    contentStream.lineTo(x, tableY + tableHeight);
                    contentStream.stroke();
                }
                // 添加表头
                contentStream.beginText();
                contentStream.setFont(PDType1Font.HELVETICA_BOLD, 12);
                contentStream.newLineAtOffset(tableX + 10, tableY + 80);
                contentStream.showText("表头 1");
                contentStream.newLineAtOffset(columnWidths[0] + 10, 0);
                contentStream.showText("表头 2");
                contentStream.newLineAtOffset(columnWidths[1] + 10, 0);
                contentStream.showText("表头 3");
                contentStream.endText();
                // 添加数据
                contentStream.beginText();
                contentStream.setFont(PDType1Font.HELVETICA, 12);
                contentStream.newLineAtOffset(tableX + 10, tableY + 50);
                contentStream.showText("数据 1");
                contentStream.newLineAtOffset(columnWidths[0] + 10, 0);
                contentStream.showText("数据 2");
                contentStream.newLineAtOffset(columnWidths[1] + 10, 0);
                contentStream.showText("数据 3");
                contentStream.endText();
            } catch (IOException e) {
                e.printStackTrace();
            }
            document.save("table_example.pdf");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

最佳实践

性能优化

  • 避免频繁创建对象:在循环中创建 PDF 相关对象(如字体、图像等)会影响性能。尽量在循环外创建并复用这些对象。
  • 使用适当的缓存机制:对于重复使用的资源(如字体、图像),可以考虑使用缓存,减少加载时间。

代码结构与维护

  • 模块化代码:将创建 PDF 的逻辑封装成独立的方法或类,提高代码的可维护性和复用性。
  • 异常处理:在创建 PDF 文档的过程中,要妥善处理各种可能的异常,确保程序的稳定性。

小结

本文详细介绍了在 Java 中创建 PDF 文档的相关知识,包括基础概念、使用 iText 和 Apache PDFBox 两个常用库的方法,以及常见实践和最佳实践。通过学习这些内容,读者能够根据自己的需求选择合适的库,并编写出高效、可维护的代码来创建功能丰富的 PDF 文档。

参考资料