java-pdf-(flying-saucer)+freemarker 生成pdf 文档
组件版本:
freemarker:2.3.26-incubating
flying-saucer-pdf:9.1.5
1.调用
@Test
public void creatPdfByFreemarker(){
String rootPath = "d:/temp/pdf/";
String fileName = "pdf-ferrmarker.pdf";
String pdf = rootPath+fileName;
String template = rootPath+"template/about.xhtml";
HashMap<String, Object> pars = new HashMap<String, Object>();
pars.put("name", "张三");
pars.put("age", 30);
pars.put("time", DateExtend.getDate());
boolean success = PdfCreator.CreateByFreemarker(template, pars, pdf);
assertTrue(success);
}
2.PdfCreator.java
package com.demo.utilis;
import java.util.HashMap;
/**
*
* @author xxj
* @version 创建时间:2017年4月27日 下午1:26:24
*/
public class PdfCreator {
/**
* 通过 freemarker 生成pdf
* @param templateFile 模板文件地址
* @param model 数据模型
* @param pdfPath 生成pdf路径
* @return
* @author xxj 2017年4月27日
*/
public static boolean CreateByFreemarker(String templateFile
,HashMap<String, Object> model
,String pdfPath){
//生成 内容
String xhtml = FreemarkerHelper.getContent(templateFile, model);
if(xhtml==null || xhtml.isEmpty()){
System.out.println("xhtml 内容为空,生成失败!");
return false;
}
//生成pdf
return PdfHelper.craetePdfByXhtml(xhtml, pdfPath, templateFile);
}
}
3.FreemarkerHelper.java
package com.demo.utilis;
import java.io.File;
import java.io.StringWriter;
import java.util.HashMap;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateExceptionHandler;
/**
*
* @author xxj
* @version 创建时间:2017年4月27日 上午11:57:11
*/
public class FreemarkerHelper {
/**
* freemarker 通过模板生成内容(模板+数据模型=内容)
* @param templateFile 模板文件地址
* @param model 数据模型
* @return
* @author xxj 2017年4月27日
*/
public static String getContent(String templateFile,HashMap<String, Object> model) {
try {
System.out.println("freemarker 读取模板:"+templateFile);
File file = new File(templateFile);
if(!file.exists())
throw new Exception("模板文件不存在:"+templateFile);
String templateDir = file.getParentFile().getPath();
String templateName =file.getName();
System.out.println("模板目录:"+templateDir);
System.out.println("模板名称:"+templateName);
//1 配置 freemarker
Configuration cfg= new Configuration(Configuration.VERSION_2_3_25);
cfg.setDirectoryForTemplateLoading(new File(templateDir));
cfg.setDefaultEncoding("UTF-8");
cfg.setOutputEncoding("UTF-8");
cfg.setLogTemplateExceptions(false);
cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
//2 生成内容
// Writer out = new OutputStreamWriter(System.out); //输出内容到控制台
StringWriter out = new StringWriter(); //输出内容到字符串流
Template temp = cfg.getTemplate(templateName);
temp.process(model, out);
out.flush();
return out.toString();
} catch (Exception ex) {
ex.printStackTrace();
throw new RuntimeException(ex.getMessage());
}
}
}
4.PdfHelper.java
package com.demo.utilis;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.w3c.dom.Document;
import org.xhtmlrenderer.pdf.ITextOutputDevice;
import org.xhtmlrenderer.pdf.ITextRenderer;
import org.xhtmlrenderer.pdf.ITextUserAgent;
import org.xhtmlrenderer.resource.XMLResource;
import org.xml.sax.InputSource;
import com.lowagie.text.pdf.BaseFont;
/**
*
* @author xxj
* @version 创建时间:2017年4月27日 上午11:58:30
*/
public class PdfHelper {
/**
* 通过 xhtml 字符串, 生成 pdf文件
* @param xhtml xhtml 内容
* @param pdfPath 生成pdf路径
* @param templatePath xhtml 模板路径,如果 xhtml 中引用了 图片,则需要该路径指定资源文件地址
* @return
* @author xxj 2017年4月27日
*/
public static boolean craetePdfByXhtml(String xhtmlContent,String pdfPath,String templatePath) {
//宋体(对应css中的 属性 font-family: SimSun; /*宋体*/)
String font1 ="C:/Windows/Fonts/simsun.ttc";
//判断系统类型,加载字体文件
java.util.Properties prop = System.getProperties();
String osName = prop.getProperty("os.name").toLowerCase();
System.out.println(osName);
if (osName.indexOf("linux")>-1) {
font1="/usr/share/fonts/simsun.ttc";
}
if(!new File(font1).exists()){
throw new RuntimeException("字体文件不存在,影响导出pdf中文显示!"+font1);
}
OutputStream os = null;
try {
String url=templatePath;
if (url.indexOf("://") == -1) {
File f = new File(url);
if (f.exists()) {
url = f.toURI().toURL().toString();
}
}
System.err.println("xhtml 地址:"+url);
System.err.println("pdf 地址:"+pdfPath);
os = new FileOutputStream(pdfPath);
ITextRenderer renderer = new ITextRenderer();
ResourceLoaderUserAgent callback = new ResourceLoaderUserAgent(renderer.getOutputDevice());
renderer.getSharedContext().setUserAgentCallback(callback);
callback.setSharedContext(renderer.getSharedContext());
//添加中文字体
renderer.getFontResolver().addFont(font1, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
renderer.setDocumentFromString(xhtmlContent,url);
renderer.layout();
renderer.createPDF(os);
os.close();
os = null;
return true;
} catch(Exception ex){
ex.printStackTrace();
return false;
}
finally {
if (os != null) {
try {
os.close();
} catch (IOException e) {
// ignore
}
}
}
}
/**
* 通过xhtml 文件生成
* @param xhtmlFilePath xhtml 文件路径
* @param pdfFilePath pdf文件路径
* @author xxj 2017年4月27日
*/
public static boolean craetePdf(String xhtmlFilePath,String pdfFilePath) {
String url=xhtmlFilePath;
String pdf=pdfFilePath;
OutputStream os = null;
try {
if (url.indexOf("://") == -1) {
// maybe it's a file
File f = new File(url);
if (f.exists()) {
url = f.toURI().toURL().toString();
}
}
System.err.println("xhtml 地址:"+url);
System.err.println("pdf 地址:"+pdf);
os = new FileOutputStream(pdf);
/*
* standard approach ITextRenderer renderer = new ITextRenderer();
*
* renderer.setDocument(url); renderer.layout();
* renderer.createPDF(os);
*/
ITextRenderer renderer = new ITextRenderer();
ResourceLoaderUserAgent callback = new ResourceLoaderUserAgent(renderer.getOutputDevice());
callback.setSharedContext(renderer.getSharedContext());
renderer.getSharedContext().setUserAgentCallback(callback);
Document doc = XMLResource.load(new InputSource(url)).getDocument();
renderer.setDocument(doc, url);
renderer.layout();
renderer.createPDF(os);
os.close();
os = null;
return true;
} catch(Exception ex){
ex.printStackTrace();
return false;
}
finally {
if (os != null) {
try {
os.close();
} catch (IOException e) {
// ignore
}
}
}
}
/**
* 资源加载代理
* @author xxj 2017年4月26日
*
*/
private static class ResourceLoaderUserAgent extends ITextUserAgent {
public ResourceLoaderUserAgent(ITextOutputDevice outputDevice) {
super(outputDevice);
}
protected InputStream resolveAndOpenStream(String uri) {
InputStream is = super.resolveAndOpenStream(uri);
System.out.println("加载pdf资源文件: " + uri);
return is;
}
}
}
5. freemarker 模板(xhtml),图片(images/flyingsaucer.png) 按照路径创建一个
<?xml version="1.0" encoding="UTF-8"?>
<!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" xml:lang="en" lang="en">
<head>
<title>Flying Saucer: CSS List Support</title>
<link rel="stylesheet" type="text/css" href="general.css" title="Style" media="screen" />
<style>
html {
background-color: transparent;
}
body {
background-color: white;
border: 0px;
margin: 0;
padding: 15;
text-align: center;
/*font-family: Arial Unicode MS;*/
font-family: SimSun; /*宋体*/
}
p {
font-size: 10pt;
}
</style>
</head>
<body>
<div style="border: 1px dotted blue; padding: 10px">
<p id="fslogo">Flying Saucer</p>
<img src="images/flyingsaucer.png" />
<p id="pagebyline">Browser Application Demo</p>
<p>An example of integrating Flying Saucer in a real application.</p>
<p><em>(This is not a real web browser)</em></p>
<p>Licensed under the GNU Lesser General Public License.</p>
</div>
<h1>hello word!</h1>
<h1>你好,世界!</h1>
<#list 1..10 as x>
<h5>===== ${x} =====</h5>
<div style="border:1px solid red;color:red;">
<h1>${name}</h1>
<h2>${age}</h2>
<h3>${time}</h3>
</div>
</#list>
</body>
</html>