使用xmlworker通过html生成pdf

xmlworker是一个基于iText的xml生成pdf工具。使用xmlworker是非常简单的,思路也很清晰。获取模板->拼装模板->生成pdf。但是在过程中还是有一些小问题需要注意下。<p/>

首先中文的问题,xmlworker默认是不支持中文的,需要修改源代码重新打包才能支持亚洲字体(修改详情)。<br/> 也可以下载我已经编好的包: 修改com.itextpdf.tool.xml.css.apply.ChunkCssApplier.java 中的 public Chunk apply(final Chunk c, final Tag t) :<br/>

    Font f = applyFontStyles(t);
    // for chinese charater display @www.micmiu.com
    if (null != HTMLUtils.bfCN && HTMLUtils.isChinese(c.getContent())) {
         f = new Font(HTMLUtils.bfCN, f.getSize(), f.getStyle(),
                   f.getColor());
    }
    float size = f.getSize();
    ......

<p/> 在com.itextpdf.tool.xml.html.HTMLUtils.java 中 增加下面用于中文字符判断的方法:

public static BaseFont bfCN = null;
 static {
      try {
           bfCN = BaseFont.createFont("STSongStd-Light", "UniGB-UCS2-H",
                     BaseFont.NOT_EMBEDDED);
      } catch (Exception e) {
      }
 }

 // add by Michael more see:http://www.micmiu.com
 private static final boolean isChinese(char c) {
      Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
      if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
                || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
                || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A
                || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION
                || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
                || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS) {
           return true;
      }
      return false;
 }
 // add by Michael more see:http://www.micmiu.com
 public static final boolean isChinese(String strName) {
      char[] ch = strName.toCharArray();
      for (int i = 0; i < ch.length; i++) {
           char c = ch[i];
           if (isChinese(c)) {
                return true;
           }
      }
      return false;
 }

其次,在写html模板的时候,因为xmlworker支持的CSS样式极少,所以模板内容要尽量简单。对于DOCTYPE和html标签的约束页比较严格。我使用的是<br/> `<!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">`。<br/> 对于一个标签中含有中文、数字或英文的时候,很可能会出现字体变形。这是因为xmlworker在渲染PDF的时候是以html的标签为单位的。只要把中文和英文分隔在不同的标签就可以了。 最后贴上代码作为参考:<br/>

<!-- lang: java -->
    import java.io.File;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.StringReader;
    import java.io.StringWriter;
    import java.io.Writer;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    
    import com.itextpdf.text.Document;
    import com.itextpdf.text.DocumentException;
    import com.itextpdf.text.pdf.PdfWriter;
    import com.itextpdf.tool.xml.XMLWorkerHelper;
    
    import freemarker.template.Configuration;
    import freemarker.template.DefaultObjectWrapper;
    import freemarker.template.Template;
    import freemarker.template.TemplateException;
    
    public class PDFOperation {
    public static void main(String[] args) throws Exception {
	// 获取html内容
	String html = getHtml();
	// 生成pdf
	createPdf(html);
    }

public static void createPdf(String html)throws DocumentException, IOException {
	String file = "E:/detail.pdf";
	Document doc = new Document();
	PdfWriter writer = PdfWriter.getInstance(doc, new FileOutputStream(file));
	doc.open();
	XMLWorkerHelper.getInstance().parseXHtml(writer, doc,new StringReader(html));
	doc.close();
}
public static String getHtml() throws IOException, TemplateException{
	Configuration cfg = new Configuration();
	cfg.setDirectoryForTemplateLoading(new File("E:/templatedir/"));
	cfg.setObjectWrapper(new DefaultObjectWrapper());
	Template t = cfg.getTemplate("test.ftl");
	Writer out = new StringWriter();
	Map<String,Object> map = new HashMap<String,Object>();
	Map<String,Object> req = new HashMap<String,Object>();
	req.put("title","XXX");
	req.put("ctime", "2014.05.06");
	req.put("province", "北京");
	List<Map<String,Object>> files = new ArrayList<Map<String,Object>>();
	Map<String,Object> file1 = new HashMap<String,Object>();
	Map<String,Object> file2 = new HashMap<String,Object>();
	file1.put("url", "http://xxx");
	file1.put("name", "FreeMarker_Manual_zh_CN.pdf");
            file1.put("ext","pdf");
	file2.put("url", "http://xxx");
	file2.put("name", "OReilly.Redis.Cookbook.2011.pdf");
            file2.put("ext","pdf");
	files.add(file1);
	files.add(file2);
	map.put("files", files);
	map.put("map",map);
	t.process(map, out);
	out.flush();
	return out.toString();
        }
    }

ftl模板:

<!-- lang: html -->
     <!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" />
    <title></title>
    </head>
    
    <body>
    <div style="padding:24px;color:#3a3b3b;background-color:#f4f4f4;line-height:28px;">
        <h1 style="color:#98989a;font-weight:bold;font-size:24px;text-align:left;">DO NOT COPY</h1>
        <div style="background-color:#fff;padding:16px 24px;width:100%;">
            <h1>${map.title}</h1>
            <h5 style="color:#848484;font-weight:normal;"><span>${map.ctime}</span></h5>
        </div>
        <div style="height:24px;">&nbsp;</div>
        <div style="background-color:#fff;padding:16px 24px;width:100%;">
            <h2>说明</h2>
            <div style="height:1px;background-color:#dbdbdb;width:100%;">&nbsp;</div>
            <div style="height:16px;width:100%;">&nbsp;</div>
            <ul style="list-style-type:none;margin:0px;padding:0px;padding-left:24px;">
                <li><span style="color:#848484">地区</span> ${map.province?default('')}</li>
            </ul>
            <#if files ?exists >
            <h3>附件</h3>
            <div style="background-color:#eee;width:100%;padding:12px;padding-left:24px;">文件</div>
            <ul style="list-style-type:none;margin:0px;padding:0px;padding-left:24px;padding-right:24px;">
     			<#list files as f>
            	<li style="margin:0px;padding:12px 0;"><a href="${f.url}"><span>${f.name}</span>.<span>${f.ext}</span></a></li>
            	</#list>
            </ul>
            </#if>
        </div>
        <h1 style="color:#98989a;font-weight:bold;font-size:24px;text-align:right;">DO NOT COPY</h1>
    </div>
    </body>
    </html>

<p/> ##以下是可能提供帮助的资料: [支持的样式表][5]<br/> [HTML生成PDF在线测试][6]<br/> [itextpdf in action中的源码样例][7]<br/> [编译好的xmlworker-cn.jar][8],如果使用maven并有私库,需要部署到私库。version=5.5.0,groupId=com.itextpdf.tool,artifactId=xmlworker-cn<br/>

转载于:https://my.oschina.net/bfleeee/blog/264670

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值