• itextpdf JAVA 输出PDF文档


    使用JAVA生成PDF的时候,还是有些注意事项需要处理的。

    第一、中文问题,默认的itext是不支持中文的,想要支持,需要做些处理。

      1、直接引用操作系统的中文字体库支持,由于此方案限制性强,又绑定了操作系统,所以此处不做实现,有兴趣可在网上搜索看看。

      2、引用itext-asian.jar包的字体支持,代码稍后上。

        itext pdf引入中文常见异常:

          com.itextpdf.text.DocumentException: Font 'STSongStd-Light' with 'UniGB-UCS2-H' is not recognized.

        解决方案:a、引入操作系统字体;2、将字体维护进jar包中,如果没有,直接找到字体放入对应jar包中,如果是路径错误,则更改包路径;3、通过itext-asian.jar来加载中文包。

    第二、表格中的设置,特别是上中下,左中右,不同的对象有不同的枚举实现,刚入手很容易混淆。其外是前景色,背景色,表格颜色等等。

    第三、输出图片,很容易报错。

        itext pdf常见输出图片异常:

        An error exists on this page. Acrobat may not display the page correctly. Please contact the person who created the PDF document to correct the problem.

        原因:PdfContentByte在addImage的时候需要在beginText()和endText()范围以外调用,否则生成的PDF就会报上述错误。

    示例:

      1 package com.itext.test;
      2 
      3 import java.io.File;
      4 import java.io.FileOutputStream;
      5 import java.io.IOException;
      6 import java.io.InputStream;
      7 import java.util.ArrayList;
      8 import java.util.List;
      9 import java.util.Random;
     10 
     11 import com.itextpdf.text.BaseColor;
     12 import com.itextpdf.text.Document;
     13 import com.itextpdf.text.DocumentException;
     14 import com.itextpdf.text.Element;
     15 import com.itextpdf.text.Font;
     16 import com.itextpdf.text.Image;
     17 import com.itextpdf.text.PageSize;
     18 import com.itextpdf.text.Paragraph;
     19 import com.itextpdf.text.Rectangle;
     20 import com.itextpdf.text.pdf.BarcodeQRCode;
     21 import com.itextpdf.text.pdf.BaseFont;
     22 import com.itextpdf.text.pdf.PdfContentByte;
     23 import com.itextpdf.text.pdf.PdfGState;
     24 import com.itextpdf.text.pdf.PdfPCell;
     25 import com.itextpdf.text.pdf.PdfPTable;
     26 import com.itextpdf.text.pdf.PdfPageEventHelper;
     27 import com.itextpdf.text.pdf.PdfWriter;
     28 
     29 public class D {
     30 
     31     private static String path = "docs/"; // 生成PDF后的存放路径
     32     private static final String logoPath = "logo.png";
     33 
     34     public static void main(String[] args) {
     35 //        T t = new T();
     36         initPDF(initData());
     37     }
     38 
     39     /**
     40      * 初始化PDF
     41      * 
     42      * @param apis
     43      */
     44     public static void initPDF(List<Api> apis) {
     45         File folder = new File(path);
     46         if (!folder.exists())
     47             folder.mkdirs(); // 创建目录
     48         Document doc = null;
     49         try {
     50             // 中文字体,要有itext-asian.jar支持(默认的itext.jar是不支持中文的)
     51             BaseFont bfchinese = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
     52             Rectangle pageSize = new Rectangle(PageSize.A4); // 页面大小设置为A4
     53             doc = new Document(pageSize, 20, 20, 40, 40); // 创建doc对象并设置边距
     54             PdfWriter writer = PdfWriter.getInstance(doc, new FileOutputStream(folder.getAbsolutePath() + File.separator + "API文档.pdf"));
     55             writer.setPageEvent(new SdkPdfPageEvent());
     56             doc.open();
     57             doc.addAuthor("Ares-xby");
     58             doc.addSubject("SDK附属API文档");
     59             doc.addTitle("API文档");
     60             BaseColor borderColor = new BaseColor(90, 140, 200);
     61             BaseColor bgColor = new BaseColor(80, 130, 180);
     62             for (Api api : apis) {
     63                 PdfPTable table = new PdfPTable({0.25f, 0.25f, 0.25f, 0.25f});
     64                 // table.setWidthPercentage(100); // 设置table宽度为100%
     65                 // table.setHorizontalAlignment(PdfPTable.ALIGN_CENTER); // 设置table居中显示
     66                 for (int i = 0; i < api.getParams().size(); i++) {
     67                     if (i == 0) {
     68                         // row 1
     69                         table.addCell(createCell("API", bfchinese, borderColor, bgColor));
     70                         table.addCell(createCell(api.getApiName(), 12, bfchinese, 3, null, borderColor, bgColor));
     71                         // row 2
     72                         table.addCell(createCell("描述", bfchinese, borderColor));
     73                         table.addCell(createCell(api.getApiDesc(), 12, bfchinese, 3, null, borderColor));
     74                     } else {
     75                         table.addCell(createCell(api.getParams().get(i).getParamName(), 10, bfchinese, null, Paragraph.ALIGN_RIGHT, borderColor));
     76                         table.addCell(createCell(api.getParams().get(i).getParamName(), 10, bfchinese, null, null, borderColor));
     77                         table.addCell(createCell(api.getParams().get(i).getParamType(), 10, bfchinese, null, null, borderColor));
     78                         table.addCell(createCell(api.getParams().get(i).getParamDesc(), 10, bfchinese, null, null, borderColor));
     79                     }
     80                 }
     81                 doc.add(table);
     82             }
     83             // 二维码
     84             BarcodeQRCode qrcode = new BarcodeQRCode("http://www.baidu.com", 1, 1, null);
     85             Image qrcodeImage = qrcode.getImage();
     86             qrcodeImage.setAbsolutePosition(10, 600);
     87             qrcodeImage.scalePercent(200);
     88             doc.add(qrcodeImage);
     89             doc.close();
     90             System.out.println("init pdf over.");
     91         } catch (DocumentException e) {
     92             e.printStackTrace();
     93         } catch (IOException e) {
     94             e.printStackTrace();
     95         } finally {
     96             if (doc != null)
     97                 doc.close();
     98         }
     99 
    100     }
    101 
    102     public static List<Api> initData() {
    103         List<Api> list = new ArrayList<Api>();
    104         for (int i = 0; i < 100; i++) {
    105             Api api = new Api();
    106             api.setApiName("api-" + i);
    107             api.setApiDesc("描述-" + i);
    108             int paramSize = new Random().nextInt(20);
    109             List<Params> paramList = new ArrayList<Params>();
    110             for (int j = 0; j < paramSize; j++) {
    111                 Params param = new Params();
    112                 param.setParamName("param-" + i + "-" + j);
    113                 param.setParamType("paramType-" + i + "-" + j);
    114                 param.setParamDesc("描述-" + i + "-" + j);
    115                 paramList.add(param);
    116             }
    117             api.setParams(paramList);
    118             list.add(api);
    119         }
    120         System.out.println("init data over. size=" + list.size());
    121         return list;
    122     }
    123     // 用於生成cell
    124     private static PdfPCell createCell(String text, BaseFont font, BaseColor borderColor) {
    125         return createCell(text, 12, font, null, null, borderColor, null);
    126     }
    127     // 用於生成cell
    128     private static PdfPCell createCell(String text, BaseFont font, BaseColor borderColor, BaseColor bgColor) {
    129         return createCell(text, 12, font, null, null, borderColor, bgColor);
    130     }
    131     // 用於生成cell
    132     private static PdfPCell createCell(String text, int fontsize, BaseFont font, Integer colspan, Integer align, BaseColor borderColor) {
    133         return createCell(text, fontsize, font, colspan, align, borderColor, null);
    134     }
    135 
    136     /**
    137      * 用於生成cell
    138      * @param text          Cell文字内容
    139      * @param fontsize      字体大小
    140      * @param font          字体
    141      * @param colspan       合并列数量
    142      * @param align         显示位置(左中右,Paragraph对象)
    143      * @param borderColor   Cell边框颜色
    144      * @param bgColor       Cell背景色
    145      * @return
    146      */
    147     private static PdfPCell createCell(String text, int fontsize, BaseFont font, Integer colspan, Integer align, BaseColor borderColor, BaseColor bgColor) {
    148         Paragraph pagragraph = new Paragraph(text, new Font(font, fontsize));
    149         PdfPCell cell = new PdfPCell(pagragraph);
    150         cell.setFixedHeight(20);
    151         cell.setVerticalAlignment(Element.ALIGN_MIDDLE); // 上中下,Element对象
    152         if (align != null)
    153             cell.setHorizontalAlignment(align);
    154         if (colspan != null && colspan > 1)
    155             cell.setColspan(colspan);
    156         if (borderColor != null)
    157             cell.setBorderColor(borderColor);
    158         if (bgColor != null)
    159             cell.setBackgroundColor(bgColor);
    160         return cell;
    161     }
    162 
    163     /**
    164      * SDK中PDF相关的PageEvent
    165      */
    166     static class SdkPdfPageEvent extends PdfPageEventHelper {
    167 
    168         @Override
    169         public void onStartPage(PdfWriter writer, Document document) {
    170             // 水印(water mark)
    171             PdfContentByte pcb = writer.getDirectContent();
    172             pcb.saveState();
    173             BaseFont bf;
    174             try {
    175                 bf = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED);
    176                 pcb.setFontAndSize(bf, 36);
    177             } catch (DocumentException e) {
    178                 e.printStackTrace();
    179             } catch (IOException e) {
    180                 e.printStackTrace();
    181             }
    182             // 透明度设置
    183             PdfGState gs = new PdfGState();
    184             gs.setFillOpacity(0.2f);
    185             pcb.setGState(gs);
    186 
    187             pcb.beginText();
    188             pcb.setTextMatrix(60, 90);
    189             pcb.showTextAligned(Element.ALIGN_LEFT, "XX公司有限公司", 200, 300, 45);
    190 
    191             pcb.endText();
    192             pcb.restoreState();
    193         }
    194 
    195         @Override
    196         public void onEndPage(PdfWriter writer, Document document) {
    197             // 页眉、页脚
    198             PdfContentByte pcb = writer.getDirectContent();
    199             try {
    200                 pcb.setFontAndSize(BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.EMBEDDED), 10);
    201             } catch (Exception e) {
    202                 e.printStackTrace();
    203             } // 支持中文字体
    204             pcb.saveState();
    205             try {
    206                 // pcb.addImage()方法要在pcb.beginText();pcb.endText();之外调用,
    207                 // 否则生成的PDF打开时会报错: An error exists on this page. Acrobat may not display the page correctly. Please contact the person who created the PDF document to correct the problem.
    208                  byte[] logoBytes = new byte[1000 * 1024]; // 此处数组大小要比logo图片大小要大, 否则图片会损坏;能够直接知道图片大小最好不过.
    209                  InputStream logoIs = getClass().getResourceAsStream(logoPath);
    210                  if(logoIs != null){
    211                      int logoSize = logoIs.read(logoBytes); // 尝试了一下,此处图片复制不完全,需要专门写个方法,将InputStream转换成Byte数组,详情参考org.apache.io.IOUtils.java的toByteArray(InputStream in)方法
    212                      if(logoSize > 0){
    213                          byte[] logo = new byte[logoSize];
    214                          System.arraycopy(logoBytes, 0, logo, 0, logoSize);
    215                          Image image = Image.getInstance(logo);// 如果直接使用logoBytes,并且图片是jar包中的话,会报图片损坏异常;本地图片可直接getInstance时候使用路径。
    216                          image.setAbsolutePosition(document.left(), document.top(-5)); // 设置图片显示位置
    217                          image.scalePercent(12);                                       // 按照百分比缩放
    218                          pcb.addImage(image);
    219                      }
    220                  }else System.err.println("logo input stream is null.");
    221             } catch (Exception e) {
    222                 System.err.println(e);
    223             }
    224             pcb.beginText();
    225 
    226             // Header
    227             float top = document.top(-15);
    228             pcb.showTextAligned(PdfContentByte.ALIGN_RIGHT, "XX开放平台API文档", document.right(), top, 0);
    229             // Footer
    230             float bottom = document.bottom(-15);
    231             pcb.showTextAligned(PdfContentByte.ALIGN_CENTER, "第 " + writer.getPageNumber() + " 页", (document.right() + document.left()) / 2, bottom, 0);
    232             pcb.endText();
    233             
    234             pcb.restoreState();
    235             pcb.closePath();
    236         }
    237     }
    238     /**
    239      * POJO for init Data.
    240      */
    241     static class Api {
    242 
    243         private String apiName;
    244         private String apiDesc;
    245         private List<Params> params;
    246 
    247         public String getApiName() {
    248             return apiName;
    249         }
    250         public void setApiName(String apiName) {
    251             this.apiName = apiName;
    252         }
    253         public String getApiDesc() {
    254             return apiDesc;
    255         }
    256         public void setApiDesc(String apiDesc) {
    257             this.apiDesc = apiDesc;
    258         }
    259         public List<Params> getParams() {
    260             return params;
    261         }
    262         public void setParams(List<Params> params) {
    263             this.params = params;
    264         }
    265     }
    266 
    267     /**
    268      * POJO for init Data.
    269      */
    270     static class Params {
    271 
    272         private String paramName;
    273         private String paramType;
    274         private String paramDesc;
    275 
    276         public String getParamName() {
    277             return paramName;
    278         }
    279         public void setParamName(String paramName) {
    280             this.paramName = paramName;
    281         }
    282         public String getParamType() {
    283             return paramType;
    284         }
    285         public void setParamType(String paramType) {
    286             this.paramType = paramType;
    287         }
    288         public String getParamDesc() {
    289             return paramDesc;
    290         }
    291         public void setParamDesc(String paramDesc) {
    292             this.paramDesc = paramDesc;
    293         }
    294     }
    295 }

    注意:

    所需jar包(itext5.0以下的包路径是com.lowagie.text,与后续版本不一致,并且直接引用中文itext-asian.jar的时候会因为lowagie名称造成路径错误,导致中文引入失败):

    itext-5.0.2.jar, itext-asian-5.1.1.jar

    也可以是itextpdf-5.5.5.jar, itext-asian-5.2.0.jar(下载)(建议使用),注意搭配不要错误。搭配的依赖原则是itext.jar或者itextpdf.jar中com.itextpdf.text.pdf.CJKFont.java中load字体所用的路径,

     itext-asian-5.1.1.jar的路径是com/itextpdf/text/pdf/fonts/cjkfonts.properties,对应itext-5.0.2.jar中CJKFont的load路径;

     itext-asian-5.2.0.jar的路径是com/itextpdf/text/pdf/fonts/cmaps/cjk_registry.properties,对应itextpdf-5.5.5.jar中CJKFont的load路径。

    最终效果:

  • 相关阅读:
    English Voice of <<Cups>>
    【线段树】奶牛排队(USACO 2007 January Gold)
    【线段树】买水果
    【线段树】卫星覆盖(NOI97)-矩阵切割
    插入排序 (Insertion Sort)
    选择排序 (Selection Sort)
    springboot整合redis
    redis入门及相关API
    mycat配置文件的详细介绍
    redis常用命令
  • 原文地址:https://www.cnblogs.com/icerainsoft/p/4900359.html
Copyright © 2020-2023  润新知