zoukankan      html  css  js  c++  java
  • 使用 itext 生成简单 pdf 文件

    截止2021年7月,itext的最新版本是itext7,本文是基于itext5编写(itext的大版本号是4-5-7,没有6)

    itext5已于2020年9月停止维护

    相关依赖:

    <!-- https://mvnrepository.com/artifact/com.itextpdf/itextpdf -->
    <dependency>
        <groupId>com.itextpdf</groupId>
        <artifactId>itextpdf</artifactId>
        <version>5.5.13.2</version>
    </dependency>
    <!-- https://mvnrepository.com/artifact/com.itextpdf/itext-asian -->
    <dependency>
        <groupId>com.itextpdf</groupId>
        <artifactId>itext-asian</artifactId>
        <version>5.2.0</version>
    </dependency>
    

    基本步骤

    用itext生成pdf大体分为5个步骤:

    os = response.getOutputStream();
    
    // 1.建立Document对象的实例
    Document doc = new Document();
    // 2.建立一个书写器(Writer)与document对象关联,通过书写器可以将文件写到输出流中
    PdfWriter.getInstance(doc, os);
    // 3.打开文档
    doc.open();
    // 4.向文档中添加内容,这部分之后会详细说明
    doc.add(new Paragraph("Hello World"));
    // 5.关闭文档
    doc.close();
    

    重点在第4步打开文档之后往里面加东西的操作。

    第2步生成了一个PdfWriter存在了doc里面,在第5步调用doc.close()的时候调用这个PdfWriterclose()方法才关闭流,所以最好写成try-with-resource的形式保证流可以关闭。

    文本

    itext的文本由文本块(Chunk)、短语(Phrase)、段落(Paragraph)构成。

    文本块(Chunk)是处理文本的最小单位,有一串带格式(包括字体、颜色、大小)的字符串组成。

    如下代码就是创建一个字体为HELVETICA、大小为10、带下划线的字符串。

    Font font = FontFactory.getFont(FontFactory.HELVETICA, 10, Font.UNDERLINE);
    Chunk chunk = new Chunk("chunk underline", font);
    

    短语(Phrase)由一个或多个文本块(Chunk)组成,短语(Phrase)也可以设定字体,但对于其中已设定过字体的文本块(Chunk)无效。通过短语(Phrase)函数add()可以将一个文本块(Chunk)加到短语(Phrase)中。

    如下代码就是创建一个包括"phrase"chunk的短语,但是"phrase"的字号是20,chunk的字号是10。

    Font font = FontFactory.getFont(FontFactory.HELVETICA, 20, Font.UNDERLINE);
    Phrase phrase = new Phrase("phrase", font);
    phrase.add(chunk);
    

    段落(Paragraph)由一个或多个文本块(Chunk)或短语(Phrase)组成,相当于WORD中的段落,同样可以设定段落的字体大小、颜色等属性。另外也可以设定段落的首行缩进、对齐方式(左对齐、右对齐、居中对齐)。通过函数setAlignment可以设定段落的对齐方式,默认为左对齐。

    Paragraph paragraph = new Paragraph("Hello World");
    // 左对齐
    paragraph.setAlignment(Element.ALIGN_LEFT);
    // 居中
    paragraph.setAlignment(Element.ALIGN_CENTER);
    // 右对齐
    paragraph.setAlignment(Element.ALIGN_RIGHT);
    // 首行缩进10个单位,不清楚这个单位是什么,但肯定不是字符
    paragraph.setFirstLineIndent(10);
    

    中文处理

    itext本身并不支持中文字体,如果把上面代码里的文字替换成中文将会输出空白文档(连换行都没有)。

    使用中日韩文字需要引入亚洲字体包itext-asian

    BaseFont baseFont = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
    Font font = new Font(baseFont, 12, Font.NORMAL);
    

    上面这段代码表示生成宋体12号字,UniGB-UCS2-H表示水平编码,UniGB-UCS2-V则是垂直编码。

    itext-asian仅支持宋体一种简体字体,可通过扩展的方式添加其他字体。

    图片

    目前itext支持gif、jpeg、png、wmf等图片格式。获取Image的方法有2种,网络图片可以通过字节数组的方式,本地图片可以直接使用路径获取。都是调用静态函数Image.getInstance(),利用Java多态的特性。

    // 根据byte[]获取
    byte[] b = bos.toByteArray();
    Image image = Image.getInstance(b);
    // 根据文件路径获取
    String path = "/user/image.jpeg";
    Image image = Image.getInstance(path);
    

    表格

    表格主要由table和cell两部分组成

    table

    // 表格有4列
    PdfPTable table = new PdfPTable(4);
    // 设置表格的宽度
    table.setTotalWidth(600);
    // 也可以每列分别设置宽度
    table.setTotalWidth(new float[] { 160, 70, 130, 100 });
    // 锁住宽度
    table.setLockedWidth(true);
    // 设置表格上面空白宽度
    table.setSpacingBefore(30f);
    // 设置表格下面空白宽度
    table.setSpacingAfter(0f);
    // 设置表格默认为无边框
    table.getDefaultCell().setBorder(0);
    doc.add(table);
    

    图片 cell

    byte[] bs = bos.toByteArray();
    Image image = Image.getInstance(bs);
    PdfPCell cell = new PdfPCell(image, true);
    // 设置cell边框(无边框),或setBorder
    cell.setBorderWidth(Rectangle.NO_BORDER);
    // 设置cell高度
    cell.setFixedHeight(100);
    // 水平居中
    cell.setHorizontalAlignment(Element.ALIGN_CENTER);
    // 垂直居中
    cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
    table.addCell(cell);
    

    在图片比较多的时候,也可使用下面的方法添加图片,这样可以省略一些重新设置格式的消耗,实测会比new一个cell稍微快一些。

    PdfPCell cell = new PdfPCell();
    cell.setFixedHeight(100);
    cell.setImage(image1);
    table.addCell(cell);
    cell.setImage(image2);
    table.addCell(cell);
    

    文本 cell

    上例cell中存放的是图片,图片高度会自适应。注意如果是文本,需要cell高度大于文字字体。比如cell高度是30,字体是14,则cell内可以写2行字,第一行放不下的字会自动到第二行。但如果字体是16,则只能放1行字,如果文本过长,长的那部分就不会显示。

    PdfPCell cell = new PdfPCell(new Paragraph("Text cell"));
    // 设置背景颜色
    cell.setBackgroundColor(BaseColor.ORANGE);
    // 设置边框颜色
    cell.setBorderColor(BaseColor.GREEN);
    // 设置左边距
    cell.setPaddingLeft(10);
    // 设置跨2行
    cell.setRowspan(2);
    // 设置跨两列
    cell.setColspan(2);
    table.addCell(cell);
    

    二维码 cell

    // 创建一个条形码对象
    Barcode128 barcode128 = new Barcode128();
    barcode128.setCode("123456789");
    barcode128.setCodeType(Barcode128.CODE128);
    // 生成条形码图片
    Image image = barcode128.createImageWithBarcode(cb, null, null);
    // 以图片的方式放到表格
    PdfPCell cell = new PdfPCell(image, true);
    cell.setHorizontalAlignment(Element.ALIGN_CENTER);
    cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
    cell.setFixedHeight(30);
    table.addCell(cell);
    

    最好给条形码设置一个合适的高度,否则黑条会过密。

    todo

    这篇文章需要补充的部分

    1. 如何导入自定义字体
    2. Image如何设置大小、透明度、自定义位置等参数
    3. 如何添加PDF文件信息
    4. 如何添加水印
    5. 如何添加页眉页脚

    等有空就写......

    2021年7月28日

    参考

    itextpdf生成表格的常见用法

    https://blog.csdn.net/u010142437/article/details/84303581

    [itext]Java生成PDF文件

    https://www.cnblogs.com/qlqwjy/p/8213989.html

    itextpdf JAVA 输出PDF文档

    https://www.cnblogs.com/icerainsoft/p/4900359.html

  • 相关阅读:
    Kubernetes实战指南(三十三):都0202了,你还在手写k8s的yaml文件?
    Hadoop学习笔记
    Anaconda、Pycharm的安装与运行和Python环境的搭建
    常用编程软件文件配置(下载安装教程)
    error C2678: 二进制“<”: 没有找到接受“const _Ty”类型的左操作数的运算符
    Java 移位运算、符号位扩展
    c++ 集合操作
    c++ 输入与缓冲区
    python 装饰器
    python global 与 nonlocal
  • 原文地址:https://www.cnblogs.com/n031/p/15073313.html
Copyright © 2011-2022 走看看