/Java /Flying-Saucer使用HTML或者FTL(Freemarker模板)生成PDF

Flying-Saucer使用HTML或者FTL(Freemarker模板)生成PDF

/Java /Flying-Saucer使用HTML或者FTL(Freemarker模板)生成PDF

  • 2015年6月4日
  •     飞翔的拖鞋up

  • Java

                   

分享到:Google+QQ空间QQ好友新浪微博更多5

  

     下载地址:http://pan.baidu.com/s/1i3pJ2PB


PDF导出工具有itext,但是itext对中文支持不好,还有样式CSS支持也不好,使用IReport比较复杂,上手不太容易,怎么办?

幸好有Flying-Saucer这个项目,帮助我们解决了以上问题!Flying-Saucer最重要的是很方便,不需要使用IReport的复杂操作,只会写html就能够做PDF导出的模板。

使用freemarker的思路

1、编写ftl模板

2、使用freemarker生成html

3、根据生成的html在生成PDF

来一张图片,否则无图无真相

/Java /Flying-Saucer使用HTML或者FTL(Freemarker模板)生成PDF_第1张图片

项目依赖

< properties >
         < servlet >3.1.0</ servlet >
         < freemarker >2.3.22</ freemarker >
         < flying-saucer >9.0.3</ flying-saucer >
     </ properties >
     < dependencies >
         < dependency >
             < groupId >javax.servlet</ groupId >
             < artifactId >javax.servlet-api</ artifactId >
             < version >${servlet}</ version >
             < scope >provided</ scope >
         </ dependency >
         < dependency >
             < groupId >org.freemarker</ groupId >
             < artifactId >freemarker</ artifactId >
             < version >${freemarker}</ version >
         </ dependency >
         < dependency >
             < groupId >org.xhtmlrenderer</ groupId >
             < artifactId >flying-saucer-pdf</ artifactId >
             < version >${flying-saucer}</ version >
         </ dependency >
     </ dependencies >


依赖关系图

/Java /Flying-Saucer使用HTML或者FTL(Freemarker模板)生成PDF_第2张图片

项目结构图

/Java /Flying-Saucer使用HTML或者FTL(Freemarker模板)生成PDF_第3张图片

主要的操作类

PdfUtils

package  org.xdemo.example.pdf;
 
import  java.io.FileOutputStream;
import  java.io.IOException;
import  java.io.OutputStream;
import  java.util.HashMap;
import  java.util.Map;
 
import  javax.servlet.http.HttpServletResponse;
 
import  org.xhtmlrenderer.pdf.ITextRenderer;
 
import  com.lowagie.text.DocumentException;
 
import  freemarker.core.ParseException;
import  freemarker.template.MalformedTemplateNameException;
import  freemarker.template.TemplateException;
import  freemarker.template.TemplateNotFoundException;
 
/**
  * PDF生成工具类
  * @author Goofy <a href="http://www.xdemo.org">http://www.xdemo.org</a>
  *
  */
public  class  PdfUtils {
 
     public  static  void  main(String[] args) {
         try  {
 
             Map<Object, Object> o= new  HashMap<Object, Object>();
             o.put( "name" "http://www.xdemo.org/" );
             
             String path=PdfHelper.getPath();
             
             generateToFile(path,  "resources/tpl.ftl" ,path+ "resources/" , o,  "D:\\xdemo.pdf" );
             
         catch  (Exception e) {
             e.printStackTrace();
         }
 
     }
     
     /**
      * 生成PDF到文件
      * @param ftlPath 模板文件路径(不含文件名)
      * @param ftlName 模板文件吗(不含路径)
      * @param imageDiskPath 图片的磁盘路径
      * @param data 数据
      * @param outputFile 目标文件(全路径名称)
      * @throws Exception
      */
     public  static  void  generateToFile(String ftlPath,String ftlName,String imageDiskPath,Object data,String outputFile)  throws  Exception {
         String html=PdfHelper.getPdfContent(ftlPath, ftlName, data);
         OutputStream out =  null ;
         ITextRenderer render =  null ;
         out =  new  FileOutputStream(outputFile);
         render = PdfHelper.getRender();
         render.setDocumentFromString(html);
         if (imageDiskPath!= null &&!imageDiskPath.equals( "" )){
             //html中如果有图片,图片的路径则使用这里设置的路径的相对路径,这个是作为根路径
             render.getSharedContext().setBaseURL( "file:/" +imageDiskPath);
         }
         render.layout();
         render.createPDF(out);
         render.finishPDF();
         render =  null ;
         out.close();
     }
     
     /**
      * 生成PDF到输出流中(ServletOutputStream用于下载PDF)
      * @param ftlPath ftl模板文件的路径(不含文件名)
      * @param ftlName ftl模板文件的名称(不含路径)
      * @param imageDiskPath 如果PDF中要求图片,那么需要传入图片所在位置的磁盘路径
      * @param data 输入到FTL中的数据
      * @param response HttpServletResponse
      * @return
      * @throws TemplateNotFoundException
      * @throws MalformedTemplateNameException
      * @throws ParseException
      * @throws IOException
      * @throws TemplateException
      * @throws DocumentException
      */
     public  static  OutputStream generateToServletOutputStream(String ftlPath,String ftlName,String imageDiskPath,Object data,HttpServletResponse response)  throws  TemplateNotFoundException, MalformedTemplateNameException, ParseException, IOException, TemplateException, DocumentException{
         String html=PdfHelper.getPdfContent(ftlPath, ftlName, data);
         OutputStream out =  null ;
         ITextRenderer render =  null ;
         out = response.getOutputStream();
         render = PdfHelper.getRender();
         render.setDocumentFromString(html);
         if (imageDiskPath!= null &&!imageDiskPath.equals( "" )){
             //html中如果有图片,图片的路径则使用这里设置的路径的相对路径,这个是作为根路径
             render.getSharedContext().setBaseURL( "file:/" +imageDiskPath);
         }
         render.layout();
         render.createPDF(out);
         render.finishPDF();
         render =  null ;
         return  out;
     }
 
}

辅助类

package  org.xdemo.example.pdf;
 
import  java.io.File;
import  java.io.IOException;
import  java.io.StringWriter;
import  java.util.Locale;
 
import  org.xhtmlrenderer.pdf.ITextRenderer;
 
import  com.lowagie.text.DocumentException;
import  com.lowagie.text.pdf.BaseFont;
 
import  freemarker.core.ParseException;
import  freemarker.template.Configuration;
import  freemarker.template.MalformedTemplateNameException;
import  freemarker.template.Template;
import  freemarker.template.TemplateException;
import  freemarker.template.TemplateNotFoundException;
 
/**
  * PDF生成辅助类
  * @author Goofy <a href="http://www.xdemo.org">http://www.xdemo.org</a>
  *
  */
@SuppressWarnings ( "deprecation" )
public  class  PdfHelper {
 
     public  static  ITextRenderer getRender()  throws  DocumentException, IOException {
 
         ITextRenderer render =  new  ITextRenderer();
 
         String path = getPath();
         //添加字体,以支持中文
         render.getFontResolver().addFont(path +  "resources/ARIALUNI.TTF" , BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
         render.getFontResolver().addFont(path +  "resources/SIMSUN.TTC" , BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
 
         return  render;
     }
 
     //获取要写入PDF的内容
     public  static  String getPdfContent(String ftlPath, String ftlName, Object o)  throws  TemplateNotFoundException, MalformedTemplateNameException, ParseException, IOException, TemplateException {
         return  useTemplate(ftlPath, ftlName, o);
     }
 
     //使用freemarker得到html内容
     public  static  String useTemplate(String ftlPath, String ftlName, Object o)  throws  TemplateNotFoundException, MalformedTemplateNameException, ParseException, IOException, TemplateException {
 
         String html =  null ;
 
         Template tpl = getFreemarkerConfig(ftlPath).getTemplate(ftlName);
         tpl.setEncoding( "UTF-8" );
 
         StringWriter writer =  new  StringWriter();
         tpl.process(o, writer);
         writer.flush();
         html = writer.toString();
         return  html;
     }
 
     /**
      * 获取Freemarker配置
      * @param templatePath
      * @return
      * @throws IOException
      */
     private  static  Configuration getFreemarkerConfig(String templatePath)  throws  IOException {
         Configuration config =  new  Configuration();
         config.setDirectoryForTemplateLoading( new  File(templatePath));
         config.setEncoding(Locale.CHINA,  "utf-8" );
         return  config;
     }
     
     /**
      * 获取类路径
      * @return
      */
     public  static  String getPath(){
         return  PdfHelper. class .getResource( "" ).getPath().substring( 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 >
< title ></ title >
< style  type = "text/css" >
body {
     margin-left: 45px;
     margin-right: 45px;
     font-family: Arial Unicode MS;
     font-size: 10px;
}
 
table {
     margin: auto;
     width: 100%;
     border-collapse: collapse;
     border: 1px solid #444444;
}
 
th,td {
     border: 1px solid #444444;
     font-size: 10px;
     margin-left: 5px;
}
 
.mcContent {
     line-height: 180%;
     padding: 20px;
}
 
.logo {
     text-align: center;
}
 
.title {
     text-align: center;
     font-weight: bold;
     font-size: 20px;
}
 
.notes {
     font-weight: normal;
     margin-left: 5px;
     margin-right: 5px;
     line-height: 18px;
}
 
.text_content {
     margin-left: 5px;
     margin-right: 5px;
     line-height: 18px;
}
 
.sum_insured_first_row {
     width: 20%;
}
 
.sum_insured_span {
     font-size: 10px;
}
 
.special_agreements_div {
     page-break-before: always;
     font-size: 14px;
     margin-top: 20px;
}
 
.special_agreements_div .special_agreements {
     font-size: 18px;
     font-weight: bold;
}
 
.title_right {
     width: 100%;
     margin: 0 auto;
}
 
.title_right p {
     text-align: left;
     margin: 0;
     margin-left: 50%;
     padding: 0;
}
 
@page {
     size: 8.5in 11in;
     @
     bottom-center
     {
     content
     :
     "page "
     counter(
     page
     )
     " of  "
     counter(
     pages
     );
}
 
.signature {
     margin: 0 auto;
     clear: both;
     font-size: 16px;
     font-weight: bold;
}
 
.signature_table {
/*     font-size: 16px; */
     font-weight: bold;
}
 
</ style >
</ head >
< body >
     作者:< a  href = "http://www.xdemo.org/" >http://www.xdemo.org/</ a >
     < div >
         < p >你好:${name}</ p >
         < div  class = "logo" > <!--这里的图片使用相对与ITextRenderer.getSharedContext().setBaseURL("file:/"+imageDiskPath);的路径-->
             图片支持< img  src = "logo1.png"  />
         </ div >
         < div >
             < p >Hello PDF: 中文支持</ p >
             < div  style = "border:1px solid red;color:red;" >
                 样式支持,红边框,红字
             </ div >
             < div  style = "border:10px solid blue;color:blue;" >
                 样式支持,蓝色10像素的边框,蓝字
             </ div >
             < hr />
             < table >
                 < tr  style = "background:gray;" >
                     < th >A</ th >
                     < th >B</ th >
                     < th >C</ th >
                     < th >D</ th >
                 </ tr >
                 < tr >
                     < td >100</ td >
                     < td >29</ td >
                     < td >32</ td >
                     < td >43</ td >
                 </ tr >
                 < tr >
                     < td >100</ td >
                     < td >29</ td >
                     < td >32</ td >
                     < td >43</ td >
                 </ tr >
                 < tr >
                     < td >100</ td >
                     < td >29</ td >
                     < td >32</ td >
                     < td >43</ td >
                 </ tr >
                 < tr >
                     < td >100</ td >
                     < td >29</ td >
                     < td >32</ td >
                     < td >43</ td >
                 </ tr >
                 < tr >
                     < td >100</ td >
                     < td >29</ td >
                     < td >32</ td >
                     < td >43</ td >
                 </ tr >
             </ table >
         </ div >
     </ div >
</ body >
</ html >

注意

本 工具类提供了两种字体支持中文,所以定义样式的时候字体只能用:simsun或者arial unicode MS,否则中文显示不出来,如需其他字体另行添加),另外请注意图片的路径问题,html中z如果有图片,图片的路径则使用这里设置的路径的相对路径,这 个是作为根路径,如

< div  class = "logo" >
     <!--这里的图片使用相对与ITextRenderer.getSharedContext().setBaseURL("file:/"+imageDiskPath);的路径-->
     图片支持< img  src = "logo1.png"  />
</ div >

如果需要PDF的下载,可以通过generateToServletOutputStream这个方法来获取PDF的输出流,然后通过response写到客户端去

转载请注明来源: http://www.xdemo.org/flying-saucer-html-freemarker-pdf/


你可能感兴趣的:(/Java /Flying-Saucer使用HTML或者FTL(Freemarker模板)生成PDF)