html转pdf。。。

来源:互联网 发布:冬季男士乳液推荐知乎 编辑:程序博客网 时间:2024/06/06 04:39

1) 编写Freemarker或者Velocity模板,打造HTML,勾画PDF的样式(请任意使用CSS) 

2) 在你的业务逻辑层引入Freemarker的引擎或者Velocity的引擎,并将业务逻辑层中可以获取的数据和模板,使用引擎生成最终的内容 

3) 将我上面的sample代码做简单封装后,调用,生成PDF
 

这样,我想作为一个web程序员来说,上面的3点,都不会成为你的绊脚石。你可以轻松驾驭PDF了。 

在Flying Saucer的官方文档中,有一些Q&A,可以解决读者们大部分的问题。包括PDF的字体、PDF的格式、Image如何处理等等。大家可以尝试着去阅读。

还有一篇文章,好像是作者写的,非常不错:http://today.java.net/pub/a/today/2007/06/26/generating-pdfs-with-flying-saucer-and-itext.html

 

 

Freemarker+Flying sauser +Itext 整合生成PDF

Freemarker、Flying sauser 、Itext ,这三个框架的作用就不详细介绍了,google一下就知道了。

Itext提供了很多底层的API,让我们可以用java代码画一个pdf出来,但是很不灵活,布局渲染代码都hard code 进java类里面了。

当需求发生改变时,哪怕只需要更改一个属性名,我们都要重新修改那段代码,很不符合开放关闭的原则。想到用模版来做渲染,但自己实现起来比较繁琐,然后google了下,找到了用freemarker做模版,Flying sauser 照着模版做渲染,让Itext做输出生成PDF的方案。

 

   freemarker和itext都比较熟悉了,Flying sauser 第一次听说,看完官方的user guide(http://flyingsaucerproject.github.com/flyingsaucer/r8/guide/users-guide-R8.html)后,自己着手做了个demo实践:

测试数据模型:

java代码:

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. package com.jeemiss.pdfsimple.entity;     
  2.     
  3. public class User {     
  4.          
  5.     private String name;     
  6.     private int age;     
  7.     private int sex;     
  8.          
  9.     /**   
  10.      * Constructor with all fields   
  11.      *    
  12.      * @param name   
  13.      * @param age   
  14.      * @param sex   
  15.      */    
  16.     public User(String name, int age, int sex) {     
  17.         super();     
  18.         this.name = name;     
  19.         this.age = age;     
  20.         this.sex = sex;     
  21.     }     
  22.          
  23.     ///////////////////////   getter and setter   ///////////////////////////////////////////     
  24.          
  25.     public String getName() {     
  26.         return name;     
  27.     }     
  28.     public void setName(String name) {     
  29.         this.name = name;     
  30.     }     
  31.     public int getAge() {     
  32.         return age;     
  33.     }     
  34.     public void setAge(int age) {     
  35.         this.age = age;     
  36.     }     
  37.     public int getSex() {     
  38.         return sex;     
  39.     }     
  40.     public void setSex(int sex) {     
  41.         this.sex = sex;     
  42.     }     
  43.          
  44.          
  45.     
  46. }    
[java] view pl

java代码:

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. package com.jeemiss.pdfsimple.freemarker;     
  2.     
  3. import freemarker.template.Configuration;     
  4.     
  5. public class FreemarkerConfiguration {     
  6.          
  7.     private static Configuration config = null;     
  8.          
  9.     /**   
  10.      * Static initialization.   
  11.      *    
  12.      * Initialize the configuration of Freemarker.   
  13.      */    
  14.     static{     
  15.         config = new Configuration();     
  16.         config.setClassForTemplateLoading(FreemarkerConfiguration.class"template");     
  17.     }     
  18.          
  19.     public static Configuration getConfiguation(){     
  20.         return config;     
  21.     }     
  22.     
  23. }    

html生成器:

java代码:

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. package com.jeemiss.pdfsimple.generator;     
  2.     
  3. import java.io.BufferedWriter;     
  4. import java.io.StringWriter;     
  5. import java.util.Map;     
  6. import com.jeemiss.pdfsimple.freemarker.FreemarkerConfiguration;     
  7. import freemarker.template.Configuration;     
  8. import freemarker.template.Template;     
  9.     
  10. public class HtmlGenerator {     
  11.          
  12.     /**   
  13.      * Generate html string.   
  14.      *    
  15.      * @param template   the name of freemarker teamlate.   
  16.      * @param variables  the data of teamlate.   
  17.      * @return htmlStr   
  18.      * @throws Exception   
  19.      */    
  20.     public static String generate(String template, Map<String,Object> variables) throws Exception{     
  21.         Configuration config = FreemarkerConfiguration.getConfiguation();     
  22.         Template tp = config.getTemplate(template);     
  23.         StringWriter stringWriter = new StringWriter();       
  24.         BufferedWriter writer = new BufferedWriter(stringWriter);       
  25.         tp.setEncoding("UTF-8");       
  26.         tp.process(variables, writer);       
  27.         String htmlStr = stringWriter.toString();     
  28.         writer.flush();       
  29.         writer.close();     
  30.         return htmlStr;     
  31.     }     
  32.     
  33. }    
[java] view plain  


pdf生成器:

java代码:

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. package com.jeemiss.pdfsimple.generator;     
  2.     
  3. import java.io.ByteArrayInputStream;     
  4. import java.io.OutputStream;     
  5. import javax.xml.parsers.DocumentBuilder;     
  6. import javax.xml.parsers.DocumentBuilderFactory;     
  7. import org.w3c.dom.Document;     
  8. import org.xhtmlrenderer.pdf.ITextRenderer;     
  9.     
  10. public class PdfGenerator {     
  11.     
  12.     /**   
  13.      * Output a pdf to the specified outputstream   
  14.      *    
  15.      * @param htmlStr the htmlstr   
  16.      * @param out the specified outputstream   
  17.      * @throws Exception   
  18.      */    
  19.     public static void generate(String htmlStr, OutputStream out)     
  20.             throws Exception {     
  21.         DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();     
  22.         Document doc = builder.parse(new ByteArrayInputStream(htmlStr.getBytes()));     
  23.         ITextRenderer renderer = new ITextRenderer();     
  24.         renderer.setDocument(doc, null);     
  25.         renderer.layout();     
  26.         renderer.createPDF(out);     
  27.         out.close();     
  28.     }     
  29.     
  30. }      


用来做测试的ftl模版,用到部分CSS3.0的属性来控制pdf强制分页和输出分页信息

html代码:

[html] view plaincopy在CODE上查看代码片派生到我的代码片
  1. <html>    
  2. <head>    
  3.   <title>${title}</title>    
  4.   <style>    
  5.      table {     
  6.              width:100%;border:green dotted ;border-width:2 0 0 2     
  7.      }     
  8.      td {     
  9.              border:green dotted;border-width:0 2 2 0     
  10.      }     
  11.      @page {       
  12.               size: 8.5in 11in;      
  13.               @bottom-center {     
  14.                     content: "page " counter(page) " of  " counter(pages);     
  15.               }     
  16.      }     
  17.   </style>    
  18. </head>    
  19. <body>    
  20.   <h1>Just a blank page.</h1>    
  21.   <div style="page-break-before:always;">    
  22.       <div align="center">    
  23.           <h1>${title}</h1>    
  24.       </div>    
  25.       <table>    
  26.          <tr>    
  27.             <td><b>Name</b></td>    
  28.             <td><b>Age</b></td>    
  29.             <td><b>Sex</b></td>    
  30.          </tr>    
  31.          <#list userList as user>    
  32.             <tr>    
  33.                 <td>${user.name}</td>    
  34.                 <td>${user.age}</td>    
  35.                 <td>    
  36.                    <#if user.sex = 1>    
  37.                          male     
  38.                    <#else>    
  39.                          female     
  40.                    </#if>    
  41.                 </td>    
  42.             </tr>    
  43.          </#list>    
  44.       </table>    
  45.   </div>    
  46. </body>    
  47. </html>       


最后写个测试用例看看:

java代码:

[java] view plaincopy在CODE上查看代码片派生到我的代码片
  1. package com.jeemiss.pdfsimple.test;     
  2.     
  3. import java.io.FileOutputStream;     
  4. import java.io.OutputStream;     
  5. import java.util.ArrayList;     
  6. import java.util.HashMap;     
  7. import java.util.List;     
  8. import java.util.Map;     
  9. import org.junit.Test;     
  10. import com.jeemiss.pdfsimple.entity.User;     
  11. import com.jeemiss.pdfsimple.generator.HtmlGenerator;     
  12. import com.jeemiss.pdfsimple.generator.PdfGenerator;     
  13.     
  14. public class TestCase      
  15. {     
  16.    @Test    
  17.    public void generatePDF() {     
  18.        try{     
  19.            String outputFile = "C:\\sample.pdf";     
  20.            Map<String,Object> variables = new HashMap<String,Object>();     
  21.                  
  22.            List<User> userList = new ArrayList<User>();     
  23.                 
  24.            User tom = new User("Tom",19,1);     
  25.            User amy = new User("Amy",28,0);     
  26.            User leo = new User("Leo",23,1);     
  27.                 
  28.            userList.add(tom);     
  29.            userList.add(amy);     
  30.            userList.add(leo);     
  31.                 
  32.            variables.put("title""User List");     
  33.            variables.put("userList", userList);     
  34.                
  35.            String htmlStr = HtmlGenerator.generate("sample.ftl", variables);     
  36.                 
  37.            OutputStream out = new FileOutputStream(outputFile);     
  38.            PdfGenerator.generate(htmlStr, out);     
  39.                 
  40.        }catch(Exception ex){     
  41.            ex.printStackTrace();     
  42.        }     
  43.             
  44.    }     
  45. }     


 

到C盘下打开sample.pdf ,看看输出的结果:


原创粉丝点击