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代码:
- package com.jeemiss.pdfsimple.entity;
-
- public class User {
-
- private String name;
- private int age;
- private int sex;
-
-
-
-
-
-
-
-
- public User(String name, int age, int sex) {
- super();
- this.name = name;
- this.age = age;
- this.sex = sex;
- }
-
-
-
- public String getName() {
- return name;
- }
- public void setName(String name) {
- this.name = name;
- }
- public int getAge() {
- return age;
- }
- public void setAge(int age) {
- this.age = age;
- }
- public int getSex() {
- return sex;
- }
- public void setSex(int sex) {
- this.sex = sex;
- }
-
-
-
- }
java代码:
- package com.jeemiss.pdfsimple.freemarker;
-
- import freemarker.template.Configuration;
-
- public class FreemarkerConfiguration {
-
- private static Configuration config = null;
-
-
-
-
-
-
- static{
- config = new Configuration();
- config.setClassForTemplateLoading(FreemarkerConfiguration.class, "template");
- }
-
- public static Configuration getConfiguation(){
- return config;
- }
-
- }
html生成器:
java代码:
- package com.jeemiss.pdfsimple.generator;
-
- import java.io.BufferedWriter;
- import java.io.StringWriter;
- import java.util.Map;
- import com.jeemiss.pdfsimple.freemarker.FreemarkerConfiguration;
- import freemarker.template.Configuration;
- import freemarker.template.Template;
-
- public class HtmlGenerator {
-
-
-
-
-
-
-
-
-
- public static String generate(String template, Map<String,Object> variables) throws Exception{
- Configuration config = FreemarkerConfiguration.getConfiguation();
- Template tp = config.getTemplate(template);
- StringWriter stringWriter = new StringWriter();
- BufferedWriter writer = new BufferedWriter(stringWriter);
- tp.setEncoding("UTF-8");
- tp.process(variables, writer);
- String htmlStr = stringWriter.toString();
- writer.flush();
- writer.close();
- return htmlStr;
- }
-
- }
pdf生成器:
java代码:
- package com.jeemiss.pdfsimple.generator;
-
- import java.io.ByteArrayInputStream;
- import java.io.OutputStream;
- import javax.xml.parsers.DocumentBuilder;
- import javax.xml.parsers.DocumentBuilderFactory;
- import org.w3c.dom.Document;
- import org.xhtmlrenderer.pdf.ITextRenderer;
-
- public class PdfGenerator {
-
-
-
-
-
-
-
-
- public static void generate(String htmlStr, OutputStream out)
- throws Exception {
- DocumentBuilder builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
- Document doc = builder.parse(new ByteArrayInputStream(htmlStr.getBytes()));
- ITextRenderer renderer = new ITextRenderer();
- renderer.setDocument(doc, null);
- renderer.layout();
- renderer.createPDF(out);
- out.close();
- }
-
- }
用来做测试的ftl模版,用到部分CSS3.0的属性来控制pdf强制分页和输出分页信息
html代码:
- <html>
- <head>
- <title>${title}</title>
- <style>
- table {
- width:100%;border:green dotted ;border-width:2 0 0 2
- }
- td {
- border:green dotted;border-width:0 2 2 0
- }
- @page {
- size: 8.5in 11in;
- @bottom-center {
- content: "page " counter(page) " of " counter(pages);
- }
- }
- </style>
- </head>
- <body>
- <h1>Just a blank page.</h1>
- <div style="page-break-before:always;">
- <div align="center">
- <h1>${title}</h1>
- </div>
- <table>
- <tr>
- <td><b>Name</b></td>
- <td><b>Age</b></td>
- <td><b>Sex</b></td>
- </tr>
- <#list userList as user>
- <tr>
- <td>${user.name}</td>
- <td>${user.age}</td>
- <td>
- <#if user.sex = 1>
- male
- <#else>
- female
- </#if>
- </td>
- </tr>
- </#list>
- </table>
- </div>
- </body>
- </html>
最后写个测试用例看看:
java代码:
- package com.jeemiss.pdfsimple.test;
-
- import java.io.FileOutputStream;
- import java.io.OutputStream;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- import org.junit.Test;
- import com.jeemiss.pdfsimple.entity.User;
- import com.jeemiss.pdfsimple.generator.HtmlGenerator;
- import com.jeemiss.pdfsimple.generator.PdfGenerator;
-
- public class TestCase
- {
- @Test
- public void generatePDF() {
- try{
- String outputFile = "C:\\sample.pdf";
- Map<String,Object> variables = new HashMap<String,Object>();
-
- List<User> userList = new ArrayList<User>();
-
- User tom = new User("Tom",19,1);
- User amy = new User("Amy",28,0);
- User leo = new User("Leo",23,1);
-
- userList.add(tom);
- userList.add(amy);
- userList.add(leo);
-
- variables.put("title", "User List");
- variables.put("userList", userList);
-
- String htmlStr = HtmlGenerator.generate("sample.ftl", variables);
-
- OutputStream out = new FileOutputStream(outputFile);
- PdfGenerator.generate(htmlStr, out);
-
- }catch(Exception ex){
- ex.printStackTrace();
- }
-
- }
- }
到C盘下打开sample.pdf ,看看输出的结果: