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

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

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();

......

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标签的约束页比较严格。我使用的是
`

`。
对于一个标签中含有中文、数字或英文的时候,很可能会出现字体变形。这是因为xmlworker在渲染PDF的时候是以html的标签为单位的。只要把中文和英文分隔在不同的标签就可以了。 最后贴上代码作为参考:

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 map = new HashMap();

Map req = new HashMap();

req.put("title","XXX");

req.put("ctime", "2014.05.06");

req.put("province", "北京");

List> files = new ArrayList>();

Map file1 = new HashMap();

Map file2 = new HashMap();

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模板:

DO NOT COPY

${map.title}

${map.ctime}

说明

  • 地区 ${map.province?default('')}

附件

文件

#list>

#if>

DO NOT COPY


[HTML生成PDF在线测试][6]
[itextpdf in action中的源码样例][7]
[编译好的xmlworker-cn.jar][8],如果使用maven并有私库,需要部署到私库。version=5.5.0,groupId=com.itextpdf.tool,artifactId=xmlworker-cn
Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐