iText生成PDF案例

wen java案例 1

本文目录导读:

iText生成PDF案例

  1. 环境准备
  2. 基础案例:创建简单PDF
  3. 进阶案例:包含表格和图片
  4. 高级案例:完整报表
  5. 内存中生成PDF
  6. PDF加密和保护
  7. 实用技巧
  8. 注意事项

我来为你提供几个iText生成PDF的实用案例,从基础到进阶。

环境准备

Maven依赖

<!-- iText 7 核心库 -->
<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itext7-core</artifactId>
    <version>7.2.5</version>
    <type>pom</type>
</dependency>
<!-- 如果需要操作中文字体 -->
<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>font-asian</artifactId>
    <version>7.2.5</version>
</dependency>

基础案例:创建简单PDF

案例1:基础文本PDF

import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.Paragraph;
import com.itextpdf.layout.element.Text;
import com.itextpdf.layout.properties.TextAlignment;
import com.itextpdf.kernel.colors.ColorConstants;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import java.io.FileOutputStream;
public class BasicPdfExample {
    public static void main(String[] args) throws Exception {
        // 1. 创建PDF写入器
        String dest = "basic_example.pdf";
        PdfWriter writer = new PdfWriter(new FileOutputStream(dest));
        // 2. 创建PDF文档
        PdfDocument pdf = new PdfDocument(writer);
        // 3. 创建文档对象
        Document document = new Document(pdf);
        // 4. 添加内容
        // 设置中文字体
        PdfFont chineseFont = PdfFontFactory.createFont(
            "STSong-Light", "UniGB-UCS2-H", true);
        // 标题
        Paragraph title = new Paragraph("iText生成PDF示例")
            .setFont(chineseFont)
            .setFontSize(18)
            .setBold()
            .setTextAlignment(TextAlignment.CENTER);
        document.add(title);
        // 正文
        Paragraph body = new Paragraph()
            .setFont(chineseFont)
            .setFontSize(12);
        body.add(new Text("这是使用iText生成的第一个PDF文档。")
            .setBold());
        body.add(new Text("\n\niText是一个强大的PDF操作库,支持:"));
        body.add(new Text("\n• 生成新的PDF文档"));
        body.add(new Text("\n• 操作现有PDF"));
        body.add(new Text("\n• 添加图片、表格、超链接等"));
        document.add(body);
        // 5. 关闭文档
        document.close();
        System.out.println("PDF生成成功!");
    }
}

进阶案例:包含表格和图片

案例2:带表格和图片的PDF

import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.*;
import com.itextpdf.layout.properties.UnitValue;
import com.itextpdf.kernel.colors.ColorConstants;
import com.itextpdf.io.image.ImageDataFactory;
import com.itextpdf.layout.borders.SolidBorder;
import java.net.URL;
public class TableImagePdfExample {
    public static void main(String[] args) throws Exception {
        String dest = "table_image_example.pdf";
        PdfWriter writer = new PdfWriter(dest);
        PdfDocument pdf = new PdfDocument(writer);
        Document document = new Document(pdf);
        // 添加标题
        document.add(new Paragraph("员工信息表")
            .setFontSize(16)
            .setBold()
            .setTextAlignment(TextAlignment.CENTER));
        // 创建表格(3列)
        float[] columnWidths = {100f, 200f, 150f};
        Table table = new Table(UnitValue.createPercentArray(columnWidths))
            .useAllAvailableWidth();
        // 添加表头
        String[] headers = {"员工ID", "姓名", "部门"};
        for (String header : headers) {
            Cell cell = new Cell()
                .add(new Paragraph(header).setBold())
                .setBackgroundColor(ColorConstants.LIGHT_GRAY)
                .setTextAlignment(TextAlignment.CENTER);
            table.addCell(cell);
        }
        // 添加数据
        String[][] data = {
            {"001", "张三", "技术部"},
            {"002", "李四", "市场部"},
            {"003", "王五", "人事部"}
        };
        for (String[] row : data) {
            for (String cellData : row) {
                table.addCell(new Cell()
                    .add(new Paragraph(cellData))
                    .setTextAlignment(TextAlignment.CENTER));
            }
        }
        // 添加表格到文档
        document.add(table);
        // 添加间距
        document.add(new Paragraph("\n"));
        // 添加图片(从文件)
        try {
            Image img = new Image(ImageDataFactory.create("path/to/your/image.jpg"));
            img.setWidth(200);
            img.setHeight(150);
            document.add(img);
        } catch (Exception e) {
            document.add(new Paragraph("图片加载失败"));
        }
        // 设置页面边框
        document.setBorder(new SolidBorder(ColorConstants.BLACK, 1));
        document.close();
        System.out.println("带表格和图片的PDF生成成功!");
    }
}

高级案例:完整报表

案例3:含样式、水印和页眉页脚的报表

import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfPage;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.canvas.PdfCanvas;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.element.*;
import com.itextpdf.layout.properties.TextAlignment;
import com.itextpdf.layout.properties.VerticalAlignment;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.colors.ColorConstants;
import com.itextpdf.kernel.events.PdfDocumentEvent;
import com.itextpdf.kernel.events.Event;
import com.itextpdf.kernel.events.IEventHandler;
import com.itextpdf.layout.Canvas;
public class AdvancedReportExample {
    // 页眉页脚处理类
    static class HeaderFooterHandler implements IEventHandler {
        private String header;
        private String footer;
        private PdfFont font;
        public HeaderFooterHandler(String header, String footer) {
            this.header = header;
            this.footer = footer;
            try {
                this.font = PdfFontFactory.createFont(
                    "STSong-Light", "UniGB-UCS2-H", true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        @Override
        public void handleEvent(Event event) {
            PdfDocumentEvent docEvent = (PdfDocumentEvent) event;
            PdfDocument pdf = docEvent.getDocument();
            PdfPage page = docEvent.getPage();
            int pageNum = pdf.getPageNumber(page);
            // 页眉
            Canvas headerCanvas = new Canvas(page, page.getPageSize());
            headerCanvas.setFont(font)
                .setFontSize(10)
                .showTextAligned(header, 
                    page.getPageSize().getWidth() / 2,
                    page.getPageSize().getTop() - 30, 
                    TextAlignment.CENTER,
                    VerticalAlignment.TOP);
            // 页脚(包含页码)
            Canvas footerCanvas = new Canvas(page, page.getPageSize());
            footerCanvas.setFont(font)
                .setFontSize(10)
                .showTextAligned(footer + " 第 " + pageNum + " 页", 
                    page.getPageSize().getWidth() / 2,
                    page.getPageSize().getBottom() + 30, 
                    TextAlignment.CENTER,
                    VerticalAlignment.BOTTOM);
        }
    }
    public static void main(String[] args) throws Exception {
        String dest = "report_example.pdf";
        PdfWriter writer = new PdfWriter(dest);
        PdfDocument pdf = new PdfDocument(writer);
        // 注册页眉页脚处理器
        pdf.addEventHandler(PdfDocumentEvent.END_PAGE, 
            new HeaderFooterHandler("年度业务报告", "公司内部资料"));
        Document document = new Document(pdf);
        // 创建中文字体
        PdfFont chineseFont = PdfFontFactory.createFont(
            "STSong-Light", "UniGB-UCS2-H", true);
        // 封面页
        document.add(new Paragraph("\n\n\n\n"));
        Paragraph title = new Paragraph("2024年度业务报告")
            .setFont(chineseFont)
            .setFontSize(24)
            .setBold()
            .setTextAlignment(TextAlignment.CENTER);
        document.add(title);
        document.add(new Paragraph("\n"));
        Paragraph subtitle = new Paragraph("业务增长与市场分析")
            .setFont(chineseFont)
            .setFontSize(16)
            .setTextAlignment(TextAlignment.CENTER);
        document.add(subtitle);
        document.add(new Paragraph("\n\n\n"));
        // 可加封面的其他信息
        Paragraph date = new Paragraph("2024年12月")
            .setFont(chineseFont)
            .setFontSize(12)
            .setTextAlignment(TextAlignment.CENTER);
        document.add(date);
        // 新页
        document.add(new AreaBreak());
        // 目录页
        document.add(new Paragraph("目录")
            .setFont(chineseFont)
            .setFontSize(18)
            .setBold());
        document.add(new Paragraph("1. 业务概览")
            .setFont(chineseFont)
            .setFontSize(12));
        document.add(new Paragraph("2. 市场分析")
            .setFont(chineseFont)
            .setFontSize(12));
        document.add(new Paragraph("3. 财务数据")
            .setFont(chineseFont)
            .setFontSize(12));
        // 新页
        document.add(new AreaBreak());
        // 使用案例3的表格方法
        addBusinessTable(document, chineseFont);
        // 添加水印(仅在特定页面)
        Thread.sleep(100); // 确保新页在前面的操作完成后
        addWatermark(pdf.getLastPage(), "机密文件");
        document.close();
        System.out.println("完整报表生成成功!");
    }
    private static void addBusinessTable(Document document, PdfFont font) {
        // 业务数据表格
        document.add(new Paragraph("业务数据汇总")
            .setFont(font)
            .setFontSize(16)
            .setBold()
            .setTextAlignment(TextAlignment.CENTER));
        float[] columnWidths = {100f, 100f, 100f, 100f};
        Table table = new Table(columnWidths);
        // 表头
        String[] headers = {"季度", "营业收入", "净利润", "同比增长"};
        for (String header : headers) {
            table.addHeaderCell(new Cell()
                .add(new Paragraph(header).setFont(font).setBold())
                .setBackgroundColor(ColorConstants.LIGHT_GRAY)
                .setTextAlignment(TextAlignment.CENTER));
        }
        // 数据
        String[][] data = {
            {"Q1", "5000万", "800万", "+5.2%"},
            {"Q2", "5500万", "950万", "+12.8%"},
            {"Q3", "6200万", "1200万", "+18.5%"},
            {"Q4", "7000万", "1500万", "+25.1%"}
        };
        for (String[] row : data) {
            for (String cellData : row) {
                table.addCell(new Cell()
                    .add(new Paragraph(cellData).setFont(font))
                    .setTextAlignment(TextAlignment.CENTER));
            }
        }
        document.add(table);
    }
    private static void addWatermark(PdfPage page, String text) {
        try {
            PdfCanvas canvas = new PdfCanvas(page);
            PdfFont font = PdfFontFactory.createFont(
                "STSong-Light", "UniGB-UCS2-H", true);
            canvas.saveState()
                .setFillColor(ColorConstants.GRAY)
                .beginText()
                .setFontAndSize(font, 60)
                .moveText(100, 400)
                .showText(text)
                .endText()
                .restoreState();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

内存中生成PDF

案例4:生成PDF到字节数组

import java.io.ByteArrayOutputStream;
public class PdfToByteArrayExample {
    public static byte[] generatePdfInMemory() throws Exception {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        PdfWriter writer = new PdfWriter(baos);
        PdfDocument pdf = new PdfDocument(writer);
        Document document = new Document(pdf);
        // 添加内容
        document.add(new Paragraph("内存中生成的PDF")
            .setFontSize(18)
            .setBold()
            .setTextAlignment(TextAlignment.CENTER));
        document.close();
        return baos.toByteArray();
    }
    public static void main(String[] args) throws Exception {
        byte[] pdfContent = generatePdfInMemory();
        // 保存到文件
        try (java.io.FileOutputStream fos = 
                new java.io.FileOutputStream("memory_pdf.pdf")) {
            fos.write(pdfContent);
        }
        // 或者作为HTTP响应返回
        // response.setContentType("application/pdf");
        // response.getOutputStream().write(pdfContent);
        System.out.println("PDF数据大小: " + pdfContent.length + " bytes");
    }
}

PDF加密和保护

案例5:带密码保护的PDF

import com.itextpdf.kernel.pdf.PdfReader;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.kernel.pdf.EncryptionConstants;
import com.itextpdf.kernel.pdf.WriterProperties;
public class PdfEncryptionExample {
    public static void main(String[] args) throws Exception {
        String src = "example.pdf";
        String dest = "encrypted_example.pdf";
        // 创建受保护的PDF
        WriterProperties writerProperties = new WriterProperties()
            .setStandardEncryption(
                "user_password".getBytes(),      // 用户密码
                "owner_password".getBytes(),     // 所有者密码
                EncryptionConstants.ALLOW_PRINTING,  // 权限
                EncryptionConstants.ENCRYPTION_AES_128  // 加密算法
            );
        PdfWriter writer = new PdfWriter(dest, writerProperties);
        PdfDocument pdf = new PdfDocument(writer);
        Document document = new Document(pdf);
        document.add(new Paragraph("这是加密的PDF文档"));
        document.close();
        // 读取加密的PDF
        PdfReader reader = new PdfReader(dest, 
            new ReaderProperties().setPassword("user_password".getBytes()));
        PdfDocument readPdf = new PdfDocument(reader);
        Document readDocument = new Document(readPdf);
        // 读取文档内容...
        readDocument.close();
    }
}

实用技巧

批量生成PDF

public class BatchPdfGenerator {
    public static void generateMultiplePdfs(List<Map<String, String>> records, 
                                           String outputDir) throws Exception {
        for (int i = 0; i < records.size(); i++) {
            Map<String, String> record = records.get(i);
            generatePdf(record, outputDir + "/report_" + i + ".pdf");
        }
    }
    private static void generatePdf(Map<String, String> data, String dest) 
            throws Exception {
        PdfWriter writer = new PdfWriter(dest);
        PdfDocument pdf = new PdfDocument(writer);
        Document document = new Document(pdf);
        // 动态生成内容
        for (Map.Entry<String, String> entry : data.entrySet()) {
            document.add(new Paragraph(entry.getKey() + ": " + entry.getValue()));
        }
        document.close();
    }
}

注意事项

  1. 字体问题:中文必须使用支持中文的字体
  2. 资源管理:记得关闭Document和PdfDocument
  3. 性能考虑:批量生成时考虑使用内存中的字节流
  4. 错误处理:添加合适的异常处理
  5. 内存管理:处理大文件时注意内存使用

这些案例覆盖了iText最常见的使用场景,你可以根据实际需求进行调整和扩展。

抱歉,评论功能暂时关闭!