使用itext将HTML模板生成PDF文件
HTML模板注意事项:
- 所有标签按语法正确闭合,否则会报错
- table用border设置表格
- 如果下载到空白文件,看看整体XML的宽度
- width使用%来设置,itext解析%
获取HTML模板
我使用的是Play 框架,基于框架可以获得数据模板;
java代码如下
//获取模板
Template template = TemplateLoader.load("/newr/supervisor/finance/FinanceManager/contractZListTemplate.html");
Map<String, Object> args = new HashMap<String, Object>();
args.put("bids", bids);
args.put("invests", invests);
args.put("users", users);
args.put("platform_url", platform_url);
args.put("amount_up_caser", amount_up_caser);
//把输入流下载为PDF文件
renderBinary(FileUtil.exportPdf(template.render(args)),"期数:"+bids.title+"融资编号:"+bids.contract_no+".pdf");
Template的源码:
/**
* Load a template
* @param path The path of the template (ex: Application/index.html)
* @return The executable template
*/
public static Template load(String path) {
Template template = null;
for (VirtualFile vf : Play.templatesPath) {
if (vf == null) {
continue;
}
VirtualFile tf = vf.child(path);
if (tf.exists()) {
template = TemplateLoader.load(tf);
break;
}
}
/*
if (template == null) {
//When using the old 'key = (file.relativePath().hashCode() + "").replace("-", "M");',
//the next line never return anything, since all values written to templates is using the
//above key.
//when using just file.relativePath() as key, the next line start returning stuff..
//therefor I have commented it out.
template = templates.get(path);
}
*/
//TODO: remove ?
if (template == null) {
VirtualFile tf = Play.getVirtualFile(path);
if (tf != null && tf.exists()) {
template = TemplateLoader.load(tf);
} else {
throw new TemplateNotFoundException(path);
}
}
return template;
}
VirtualFile源码
package play.vfs;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.channels.Channel;
import java.nio.channels.FileChannel;
import java.security.AccessControlException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import play.Play;
import play.exceptions.UnexpectedException;
import play.libs.IO;
/**
* The VFS used by Play!
*/
public class VirtualFile {
File realFile;
VirtualFile(File file) {
this.realFile = file;
}
public String getName() {
return realFile.getName();
}
public boolean isDirectory() {
return realFile.isDirectory();
}
public String relativePath() {
List<String> path = new ArrayList<String>();
File f = realFile;
String prefix = "{?}";
while (true) {
path.add(f.getName());
f = f.getParentFile();
if (f == null) {
break; // ??
}
if (f.equals(Play.frameworkPath)) {
prefix = "{play}";
break;
}
if (f.equals(Play.applicationPath)) {
prefix = "";
break;
}
String module = isRoot(f);
if (module != null) {
prefix = module;
break;
}
}
Collections.reverse(path);
StringBuilder builder = new StringBuilder();
for (String p : path) {
builder.append("/" + p);
}
return prefix + builder.toString();
}
String isRoot(File f) {
for (VirtualFile vf : Play.roots) {
if (vf.realFile.getAbsolutePath().equals(f.getAbsolutePath())) {
return "{module:" + vf.getName() + "}";
}
}
return null;
}
public List<VirtualFile> list() {
List<VirtualFile> res = new ArrayList<VirtualFile>();
if (exists()) {
File[] children = realFile.listFiles();
for (int i = 0; i < children.length; i++) {
res.add(new VirtualFile(children[i]));
}
}
return res;
}
public boolean exists() {
try {
if (realFile != null) {
return realFile.exists();
}
return false;
} catch (AccessControlException e) {
return false;
}
}
public InputStream inputstream() {
try {
return new FileInputStream(realFile);
} catch (Exception e) {
throw new UnexpectedException(e);
}
}
public OutputStream outputstream() {
try {
return new FileOutputStream(realFile);
} catch (Exception e) {
throw new UnexpectedException(e);
}
}
public Long lastModified() {
if (realFile != null) {
return realFile.lastModified();
}
return 0L;
}
@Override
public boolean equals(Object other) {
if (other instanceof VirtualFile) {
VirtualFile vf = (VirtualFile) other;
if (realFile != null && vf.realFile != null) {
return realFile.equals(vf.realFile);
}
}
return super.equals(other);
}
@Override
public int hashCode() {
if (realFile != null) {
return realFile.hashCode();
}
return super.hashCode();
}
public long length() {
return realFile.length();
}
public VirtualFile child(String name) {
return new VirtualFile(new File(realFile, name));
}
public Channel channel() {
try {
FileInputStream fis = new FileInputStream(realFile);
FileChannel ch = fis.getChannel();
return ch;
} catch (FileNotFoundException e) {
return null;
}
}
public static VirtualFile open(String file) {
return open(new File(file));
}
public static VirtualFile open(File file) {
return new VirtualFile(file);
}
public String contentAsString() {
try {
return IO.readContentAsString(inputstream());
} catch (Exception e) {
throw new UnexpectedException(e);
}
}
public File getRealFile() {
return realFile;
}
public void write(CharSequence string) {
try {
IO.writeContent(string, outputstream());
} catch (Exception e) {
throw new UnexpectedException(e);
}
}
public byte[] content() {
byte[] buffer = new byte[(int) length()];
try {
InputStream is = inputstream();
is.read(buffer);
is.close();
return buffer;
} catch (Exception e) {
throw new UnexpectedException(e);
}
}
@Override
public String toString() {
return getName();
}
public static VirtualFile search(Collection<VirtualFile> roots, String path) {
for (VirtualFile file : roots) {
if (file.child(path).exists()) {
return file.child(path);
}
}
return null;
}
public static VirtualFile fromRelativePath(String relativePath) {
Pattern pattern = Pattern.compile("^(\\{(.+?)\\})?(.*)$");
Matcher matcher = pattern.matcher(relativePath);
if(matcher.matches()) {
String path = matcher.group(3);
String module = matcher.group(2);
if(module == null || module.equals("?") || module.equals("")) {
return new VirtualFile(Play.applicationPath).child(path);
} else {
if(module.equals("play")) {
return new VirtualFile(Play.frameworkPath).child(path);
}
if(module.startsWith("module:")){
module = module.substring("module:".length());
for(Entry<String, VirtualFile> entry : Play.modules.entrySet()) {
if(entry.getKey().equals(module))
return entry.getValue().child(path);
}
}
}
}
return null;
}
}
生成PDF工具类
/**
*生成PDF工具类
*/
public static InputStream exportPdf(String content) {
ByteArrayOutputStream fos = null;
Document document = new Document();
try {
fos = new ByteArrayOutputStream();
PdfWriter writer = PdfWriter.getInstance(document, fos);
document.open();
InputStream htmlInput = new ByteArrayInputStream(content.getBytes("UTF-8"));
// 使用我们的字体提供器,并将其设置为unicode字体样式
MyFontsProvider fontProvider = new MyFontsProvider();
fontProvider.addFontSubstitute("lowagie", "garamond");
fontProvider.setUseUnicode(true);
CssAppliers cssAppliers = new CssAppliersImpl(fontProvider);
HtmlPipelineContext htmlContext = new HtmlPipelineContext(cssAppliers);
htmlContext.setTagFactory(Tags.getHtmlTagProcessorFactory());
XMLWorkerHelper.getInstance().getDefaultCssResolver(true);
XMLWorkerHelper.getInstance().parseXHtml(writer, document, htmlInput, null, Charset.forName("UTF-8"),
fontProvider);
document.close();
writer.close();
InputStream resultInputStream = new ByteArrayInputStream(fos.toByteArray());
return resultInputStream;
} catch (Exception e) {
throw new RuntimeException("Export PDF error : ", e);
}
}
解决中文乱码问题及设置字体
/**
* 重写 字符设置方法,解决中文乱码问题
*
*/
public static class MyFontsProvider extends XMLWorkerFontProvider {
public MyFontsProvider(){
super(null, null);
}
@Override
public Font getFont(final String fontname, String encoding, float size, final int style) {
String fntname = fontname;
if (fntname == null) {
fntname = "宋体";
}
if (size == 0) {
size = 4;
}
return super.getFont(fntname, encoding, size, style);
}
}