Spring boot 使用iText导出PDF 几种方式

1、 iText 介绍

       iText是用于生成PDF文档的一个java类库。通过iText不仅可以生成PDF或rtf的文档,而且可以将XML、Html文件转化为PDF文件。官网地址http://itextpdf.com。

2、Spring boot项目 iText 依赖

itextpdf.jar是iText的核心库,提供了用于创建和操作PDF文档的基本功能,itext-asian.jar是itext库中关于亚洲编码的类库,特别适用于处理中文字符,处理中文乱码。

 <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.5.11</version>
 </dependency>
 <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itext-asian</artifactId>
            <version>5.2.0</version>
  </dependency>

3、实现方式 

  3.1 一般性(不复杂PDF)处理

下面写了junit测试。

@Test
public void testPdf() {
    try {
        Document document = new Document();
        PdfWriter writer PdfWriter.getInstance(document, new 
          FileOutputStream("d:/hello.pdf"));
        document.open();
        Element element = new Paragraph("helloword!");
        document.add(element);
        document.close();
    } catch (DocumentException e) {
        e.printStackTrace();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }finally {
                doc.close();
                writer.close();
     }
}

如果要实现Http 导出PDF,代码如下

public void exportPdf(HttpServletResponse response) {
    try {
        Document document = new Document();
        OutputStream out = response.getOutputStream();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        PdfWriter writer PdfWriter.getInstance(document, new 
         baos);
        document.open();
        Element element = new Paragraph("helloword!");
        document.add(element);
        response.setContentType("application/pdf");
        response.setHeader("Content-Disposition", "inline; filename=chat_export.pdf");
        out.write(baos.toByteArray());
        out.flush();
    } catch (DocumentException e) {
        e.printStackTrace();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    }finally {   
                 // 关闭流....
                

     }
}

3.2 格式、样式复杂的Pdf处理

    在处理格式和样式复杂的pdf时候,为排版的美观,需要拼接html,再将html转成pdf。我这里手动拼接html,此时需要依赖xmlworker包,

 <dependency>
            <groupId>com.itextpdf.tool</groupId>
            <artifactId>xmlworker</artifactId>
            <version>5.5.13.2</version>
  </dependency>

     形成html方法定义,这里可以定义很多格式和样式,实现自由扩展。

    private  String createHtml(String base64,Map<String,Object> headMap,List data){
        StringBuffer stringBuffer = new StringBuffer();
        createHtmlPic(stringBuffer,base64);
       // 传入headMap,是为了支持动态表头
        createHtmlTableHead(stringBuffer,headMap);
        createHtmlTableData(stringBuffer,data);
        return  stringBuffer.toString() ;
    }

   生成pdf 方法

  public void exportPdfData(String base64,Map<String,Object> headMap,List data,String dir) {
        File outFile = new File(dir);
        // 创建动态html
        String strHtml =  createHtml( base64, headMap, data);
        //html 转pdf
        BaseFont bfChinese = null;
        try {
            bfChinese = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
  

        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }catch (Exception e){
            e.printStackTrace();
            e.printStackTrace();
        }
        Font font = new Font(bfChinese, 9, Font.NORMAL);
        font1.setColor(new BaseColor(255,255,255));
        Document doc = new Document(new RectangleReadOnly(842F, 595F));
        PdfWriter writer =null;
        try {
            writer = PdfWriter.getInstance(doc,new FileOutputStream(dir));
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

        //设置页面边距
        doc.setMargins(20, 15, 20, 55);
        if (writer != null){
            writer.setPageEvent(new PageMarker());
        }
        doc.open();
        try {
            XMLWorkerHelper.getInstance().parseXHtml(writer, doc, new ByteArrayInputStream(strHtml.getBytes("UTF-8")), Charset.forName("UTF-8"),new FontProvider() {
                @Override
                public boolean isRegistered(String arg0) {
                    return false;
                }
                @Override
                public Font getFont(String fontFamily, String charset, boolean arg2, float size, int style, BaseColor color) {
                    if("STSongStd-Light1".equals(fontFamily)){
                        return  font1 ;
                    }else {
                        return font1 ;
                    }
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            doc.close();
            writer.close();
        }
    
    }

入要http生成并且导出pdf,请参照3.1,本例子是我手动代码拼接html。

3.3、使用iText-Html-Freemarker实现pdf

     其实3.3 和3.2 原理是一样的(都是将html转pdf),只是3.3加入模板引擎支持,可以使用FreeMarker。需要加入如下依赖。

     <dependency>

         <groupId>org.freemarker</groupId>

         <artifactId>freemarker</artifactId>

         <version>2.3.19</version>

     </dependency>

 添加模板freemarker.html   

  <!DOCTYPE html>

     <html lang="en">

         <head>

             <meta charset="UTF-8"/>

             <title>freemarker渲染HTML演示</title>

         </head>

         <body>

              <div>${studentName}</div>
               <div>${age}</div>
         </body>

     </html>

 读取模板转出动态html

      Configuration freemarkerConfig = new Configuration();

            //设置freemarker模板目录

              freemarkerConfig.setDirectoryForTemplateLoading(new File("/export/pdf/"));

            //获取指定的模板文件

            Template template = freemarkerConfig.getTemplate("freemarker.html");

            //设置编码方式

            template.setEncoding("UTF-8");

            //合并数据模型与模板,将合并后的数据和模板写入到流中,这里使用的字符流

            Writer out = new StringWriter();

            template.process(data, out);

            out.flush();

            String content = out.toString();

 生产pdf

  public void exportPdfData(String strHtml String dir) {
        File outFile = new File(dir);
           BaseFont bfChinese = null;
        try {
            bfChinese = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
  

        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }catch (Exception e){
            e.printStackTrace();
            e.printStackTrace();
        }
        Font font = new Font(bfChinese, 9, Font.NORMAL);
        font1.setColor(new BaseColor(255,255,255));
        Document doc = new Document(new RectangleReadOnly(842F, 595F));
        PdfWriter writer =null;
        try {
            writer = PdfWriter.getInstance(doc,new FileOutputStream(dir));
        } catch (DocumentException e) {
            e.printStackTrace();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }

        //设置页面边距
        doc.setMargins(20, 15, 20, 55);
        if (writer != null){
            writer.setPageEvent(new PageMarker());
        }
        doc.open();
        try {
            XMLWorkerHelper.getInstance().parseXHtml(writer, doc, new ByteArrayInputStream(strHtml.getBytes("UTF-8")), Charset.forName("UTF-8"),new FontProvider() {
                @Override
                public boolean isRegistered(String arg0) {
                    return false;
                }
                @Override
                public Font getFont(String fontFamily, String charset, boolean arg2, float size, int style, BaseColor color) {
                    if("STSongStd-Light1".equals(fontFamily)){
                        return  font1 ;
                    }else {
                        return font1 ;
                    }
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            doc.close();
            writer.close();
        }
    
    }

    

4 、注意

      如果已经导入itext-asian依赖之后,还是出现中文乱码。可能是你使用的字体在你部署的服务上不存在。一般在windows机器找到对应的字体, 复制到对应目录,如果部署在linux要复制/usr/share/fonts目录。 一般要修改此目录的权限,并且执行sudo fc-cache -fv  命令,是字体生效。

  • 32
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值