首页 > 编程 > Java > 正文

java根据模板动态生成PDF实例

2019-11-26 12:26:35
字体:
来源:转载
供稿:网友

一、需求说明:

根据业务需要,需要在服务器端生成可动态配置的PDF文档,方便数据可视化查看。

二、解决方案:

iText+FreeMarker+JFreeChart生成可动态配置的PDF文档

iText有很强大的PDF处理能力,但是样式和排版不好控制,直接写PDF文档,数据的动态渲染很麻烦。

FreeMarker能配置动态的html模板,正好解决了样式、动态渲染和排版问题。

JFreeChart有这方便的画图API,能画出简单的折线、柱状和饼图,基本能满足需要。

三、实现功能:

1、能动态配置PDF文档内容

2、能动态配置中文字体显示

3、设置自定义的页眉页脚信息

4、能动态生成业务图片

5、完成PDF的分页和图片的嵌入

四、主要代码结构说明:

1、component包:PDF生成的组件 对外提供的是PDFKit工具类和HeaderFooterBuilder接口,其中PDFKit负责PDF的生成,HeaderFooterBuilder负责自定义页眉页脚信息。

2、builder包:负责PDF模板之外的额外信息填写,这里主要是页眉页脚的定制。

3、chart包:JFreeChart的画图工具包,目前只有一个线形图。

4、test包:测试工具类

5、util包:FreeMarker等工具类。

五、关键代码说明:

1、模板配置

 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head>  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>  <meta http-equiv="Content-Style-Type" content="text/css"/>  <title></title>  <style type="text/css">    body {      font-family: pingfang sc light;    }    .center{      text-align: center;      width: 100%;    }  </style></head><body><!--第一页开始--><div class="page" >  <div class="center"><p>${templateName}</p></div>  <div><p>iText官网:${ITEXTUrl}</p></div>  <div><p>FreeMarker官网:${freeMarkerUrl}</p></div>  <div><p>JFreeChart教程:${JFreeChartUrl}</p></div>  <div>列表值:</div>  <div>    <#list scores as item>      <div><p>${item}</p></div>    </#list>  </div></div><!--第一页结束--><!---分页标记--><span style="page-break-after:always;"></span><!--第二页开始--><div class="page">  <div>第二页开始了</div>  <!--外部链接-->  <p>百度图标</p>  <div>    <img src="${imageUrl}" alt="百度图标" width="270" height="129"/>  </div>  <!--动态生成的图片-->  <p>气温变化对比图</p>  <div>    <img src="${picUrl}" alt="我的图片" width="500" height="270"/>  </div></div><!--第二页结束--></body></html>

2、获取模板内容并填充数据

/** * @description 获取模板 */public static String getContent(String fileName,Object data){  String templatePath=getPDFTemplatePath(fileName);//根据PDF名称查找对应的模板名称  String templateFileName=getTemplateName(templatePath);  String templateFilePath=getTemplatePath(templatePath);  if(StringUtils.isEmpty(templatePath)){    throw new FreeMarkerException("templatePath can not be empty!");  }  try{    Configuration config = new Configuration(Configuration.VERSION_2_3_25);//FreeMarker配置    config.setDefaultEncoding("UTF-8");    config.setDirectoryForTemplateLoading(new File(templateFilePath));//注意这里是模板所在文件夹,不是文件    config.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);    config.setLogTemplateExceptions(false);    Template template = config.getTemplate(templateFileName);//根据模板名称 获取对应模板    StringWriter writer = new StringWriter();    template.process(data, writer);//模板和数据的匹配    writer.flush();    String html = writer.toString();    return html;  }catch (Exception ex){    throw new FreeMarkerException("FreeMarkerUtil process fail",ex);  }}

3、导出模板到PDF文件

/**   * @description   导出pdf到文件   * @param fileName 输出PDF文件名   * @param data   模板所需要的数据   *   */public String exportToFile(String fileName,Object data){   String htmlData= FreeMarkerUtil.getContent(fileName, data);//获取FreeMarker的模板数据  if(StringUtils.isEmpty(saveFilePath)){    saveFilePath=getDefaultSavePath(fileName);//设置PDF文件输出路径  }  File file=new File(saveFilePath);  if(!file.getParentFile().exists()){    file.getParentFile().mkdirs();  }  FileOutputStream outputStream=null;  try{    //设置输出路径    outputStream=new FileOutputStream(saveFilePath);    //设置文档大小    Document document = new Document(PageSize.A4);//IText新建PDF文档    PdfWriter writer = PdfWriter.getInstance(document, outputStream);//设置文档和输出流的关系    //设置页眉页脚    PDFBuilder builder = new PDFBuilder(headerFooterBuilder,data);    builder.setPresentFontSize(10);    writer.setPageEvent(builder);    //输出为PDF文件    convertToPDF(writer,document,htmlData);  }catch(Exception ex){    throw new PDFException("PDF export to File fail",ex);  }finally{    IOUtils.closeQuietly(outputStream);  }  return saveFilePath;}

4、测试工具类

 public String createPDF(Object data, String fileName){      //pdf保存路径      try {        //设置自定义PDF页眉页脚工具类        PDFHeaderFooter headerFooter=new PDFHeaderFooter();        PDFKit kit=new PDFKit();        kit.setHeaderFooterBuilder(headerFooter);        //设置输出路径        kit.setSaveFilePath("/Users/fgm/Desktop/pdf/hello.pdf”);//设置出书路径        String saveFilePath=kit.exportToFile(fileName,data);        return saveFilePath;      } catch (Exception e) {        log.error("PDF生成失败{}", ExceptionUtils.getFullStackTrace(e));        return null;      }        }  
 public static void main(String[] args) {     ReportKit360 kit=new ReportKit360();        TemplateBO templateBO=new TemplateBO();//配置模板数据        templateBO.setTemplateName("Hello iText! Hello freemarker! Hello jFreeChart!");        templateBO.setFreeMarkerUrl("http://www.zheng-hang.com/chm/freemarker2_3_24/ref_directive_if.html");        templateBO.setITEXTUrl("http://developers.itextpdf.com/examples-itext5");    templateBO.setJFreeChartUrl("http://www.yiibai.com/jfreechart/jfreechart_referenced_apis.html");    templateBO.setImageUrl("https://ss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/logo/bd_logo1_31bdc765.png");               List<String> scores=new ArrayList<String>();        scores.add("90");        scores.add("95");        scores.add("98");        templateBO.setScores(scores);        List<Line> lineList=getTemperatureLineList();        TemperatureLineChart lineChart=new TemperatureLineChart();        String picUrl=lineChart.draw(lineList,0);//自定义的数据画图        templateBO.setPicUrl(picUrl);        String path= kit.createPDF(templateBO,"hello.pdf");      System.out.println(path);        }

六、生成效果图:

七、项目完整代码

1、github地址:https://github.com/superad/pdf-kit

八、遇到的坑:

1、FreeMarker配置模板文件样式,在实际PDF生成过程中,可能会出现一些不一致的情形,目前解决方法,就是换种方式调整样式。

2、字体文件放在resource下,在打包时会报错,运行mvn -X compile 会看到详细错误:

这是字体文件是二进制的,而maven项目中配置了资源文件的过滤,不能识别二进制文件导致的,plugins中增加下面这个配置就好了:

<build>  <resources>    <resource>      <directory>src/main/resources</directory>      <filtering>true</filtering>    </resource>  </resources>  <!--增加的配置,过滤ttf文件的匹配-->  <plugins>    <plugin>      <groupId>org.apache.maven.plugins</groupId>      <artifactId>maven-resources-plugin</artifactId>      <version>2.7</version>      <configuration>        <encoding>UTF-8</encoding>        <nonFilteredFileExtensions>          <nonFilteredFileExtension>ttf</nonFilteredFileExtension>        </nonFilteredFileExtensions>      </configuration>    </plugin>  </plugins></build>

3、PDF分页配置:

在ftl文件中,增加分页标签: <span style="page-break-after:always;"></span>

九、 完整maven配置:

<!--pdf生成 itext-->  <dependency>    <groupId>com.itextpdf</groupId>    <artifactId>itextpdf</artifactId>    <version>5.4.2</version>   </dependency> <dependency>  <groupId>com.itextpdf.tool</groupId>  <artifactId>xmlworker</artifactId>  <version>5.4.1</version></dependency><dependency>  <groupId>com.itextpdf</groupId>  <artifactId>itext-asian</artifactId>  <version>5.2.0</version></dependency><dependency>  <groupId>org.xhtmlrenderer</groupId>  <artifactId>flying-saucer-pdf</artifactId>  <version>9.0.3</version></dependency><!--freemarker--><dependency>  <groupId>org.freemarker</groupId>  <artifactId>freemarker</artifactId>  <version>2.3.26-incubating</version></dependency><!--jfreechart--><dependency>  <groupId>jfreechart</groupId>  <artifactId>jfreechart</artifactId>  <version>1.0.0</version></dependency><!--log--><dependency>  <groupId>ch.qos.logback</groupId>  <artifactId>logback-core</artifactId>  <version>1.0.13</version></dependency><dependency>  <groupId>ch.qos.logback</groupId>  <artifactId>logback-classic</artifactId>  <version>1.0.13</version></dependency><dependency>  <groupId>ch.qos.logback</groupId>  <artifactId>logback-access</artifactId>  <version>1.0.13</version></dependency><dependency>  <groupId>org.slf4j</groupId>  <artifactId>slf4j-api</artifactId>  <version>1.7.5</version></dependency><dependency>  <groupId>org.slf4j</groupId>  <artifactId>log4j-over-slf4j</artifactId>  <version>1.7.21</version></dependency><!--util--><dependency>  <groupId>com.google.guava</groupId>  <artifactId>guava</artifactId>  <version>20.0</version></dependency><dependency>  <groupId>org.projectlombok</groupId>  <artifactId>lombok</artifactId>  <version>1.14.8</version></dependency><dependency>  <groupId>org.apache.commons</groupId>  <artifactId>commons-io</artifactId>  <version>1.3.2</version></dependency><dependency>  <groupId>commons-lang</groupId>  <artifactId>commons-lang</artifactId>  <version>2.6</version></dependency><!--servlet--><dependency>  <groupId>javax.servlet</groupId>  <artifactId>servlet-api</artifactId>  <version>2.5</version></dependency>

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持武林网。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表