/Java /Flying-Saucer使用HTML或者FTL(Freemarker模板)生成PDF
飞翔的拖鞋up
Java
分享到:Google+QQ空间QQ好友新浪微博更多5
下载地址:http://pan.baidu.com/s/1i3pJ2PB
PDF导出工具有itext,但是itext对中文支持不好,还有样式CSS支持也不好,使用IReport比较复杂,上手不太容易,怎么办?
幸好有Flying-Saucer这个项目,帮助我们解决了以上问题!Flying-Saucer最重要的是很方便,不需要使用IReport的复杂操作,只会写html就能够做PDF导出的模板。
使用freemarker的思路
1、编写ftl模板
2、使用freemarker生成html
3、根据生成的html在生成PDF
来一张图片,否则无图无真相
项目依赖
<
properties
>
<
servlet
>3.1.0</
servlet
>
<
freemarker
>2.3.22</
freemarker
>
<
flying-saucer
>9.0.3</
flying-saucer
>
</
properties
>
<
dependencies
>
<
dependency
>
<
groupId
>javax.servlet</
groupId
>
<
artifactId
>javax.servlet-api</
artifactId
>
<
version
>${servlet}</
version
>
<
scope
>provided</
scope
>
</
dependency
>
<
dependency
>
<
groupId
>org.freemarker</
groupId
>
<
artifactId
>freemarker</
artifactId
>
<
version
>${freemarker}</
version
>
</
dependency
>
<
dependency
>
<
groupId
>org.xhtmlrenderer</
groupId
>
<
artifactId
>flying-saucer-pdf</
artifactId
>
<
version
>${flying-saucer}</
version
>
</
dependency
>
</
dependencies
>
|
依赖关系图
项目结构图
主要的操作类
PdfUtils
package
org.xdemo.example.pdf;
import
java.io.FileOutputStream;
import
java.io.IOException;
import
java.io.OutputStream;
import
java.util.HashMap;
import
java.util.Map;
import
javax.servlet.http.HttpServletResponse;
import
org.xhtmlrenderer.pdf.ITextRenderer;
import
com.lowagie.text.DocumentException;
import
freemarker.core.ParseException;
import
freemarker.template.MalformedTemplateNameException;
import
freemarker.template.TemplateException;
import
freemarker.template.TemplateNotFoundException;
/**
* PDF生成工具类
* @author Goofy <a href="http://www.xdemo.org">http://www.xdemo.org</a>
*
*/
public
class
PdfUtils {
public
static
void
main(String[] args) {
try
{
Map<Object, Object> o=
new
HashMap<Object, Object>();
o.put(
"name"
,
"http://www.xdemo.org/"
);
String path=PdfHelper.getPath();
generateToFile(path,
"resources/tpl.ftl"
,path+
"resources/"
, o,
"D:\\xdemo.pdf"
);
}
catch
(Exception e) {
e.printStackTrace();
}
}
/**
* 生成PDF到文件
* @param ftlPath 模板文件路径(不含文件名)
* @param ftlName 模板文件吗(不含路径)
* @param imageDiskPath 图片的磁盘路径
* @param data 数据
* @param outputFile 目标文件(全路径名称)
* @throws Exception
*/
public
static
void
generateToFile(String ftlPath,String ftlName,String imageDiskPath,Object data,String outputFile)
throws
Exception {
String html=PdfHelper.getPdfContent(ftlPath, ftlName, data);
OutputStream out =
null
;
ITextRenderer render =
null
;
out =
new
FileOutputStream(outputFile);
render = PdfHelper.getRender();
render.setDocumentFromString(html);
if
(imageDiskPath!=
null
&&!imageDiskPath.equals(
""
)){
//html中如果有图片,图片的路径则使用这里设置的路径的相对路径,这个是作为根路径
render.getSharedContext().setBaseURL(
"file:/"
+imageDiskPath);
}
render.layout();
render.createPDF(out);
render.finishPDF();
render =
null
;
out.close();
}
/**
* 生成PDF到输出流中(ServletOutputStream用于下载PDF)
* @param ftlPath ftl模板文件的路径(不含文件名)
* @param ftlName ftl模板文件的名称(不含路径)
* @param imageDiskPath 如果PDF中要求图片,那么需要传入图片所在位置的磁盘路径
* @param data 输入到FTL中的数据
* @param response HttpServletResponse
* @return
* @throws TemplateNotFoundException
* @throws MalformedTemplateNameException
* @throws ParseException
* @throws IOException
* @throws TemplateException
* @throws DocumentException
*/
public
static
OutputStream generateToServletOutputStream(String ftlPath,String ftlName,String imageDiskPath,Object data,HttpServletResponse response)
throws
TemplateNotFoundException, MalformedTemplateNameException, ParseException, IOException, TemplateException, DocumentException{
String html=PdfHelper.getPdfContent(ftlPath, ftlName, data);
OutputStream out =
null
;
ITextRenderer render =
null
;
out = response.getOutputStream();
render = PdfHelper.getRender();
render.setDocumentFromString(html);
if
(imageDiskPath!=
null
&&!imageDiskPath.equals(
""
)){
//html中如果有图片,图片的路径则使用这里设置的路径的相对路径,这个是作为根路径
render.getSharedContext().setBaseURL(
"file:/"
+imageDiskPath);
}
render.layout();
render.createPDF(out);
render.finishPDF();
render =
null
;
return
out;
}
}
|
辅助类
package
org.xdemo.example.pdf;
import
java.io.File;
import
java.io.IOException;
import
java.io.StringWriter;
import
java.util.Locale;
import
org.xhtmlrenderer.pdf.ITextRenderer;
import
com.lowagie.text.DocumentException;
import
com.lowagie.text.pdf.BaseFont;
import
freemarker.core.ParseException;
import
freemarker.template.Configuration;
import
freemarker.template.MalformedTemplateNameException;
import
freemarker.template.Template;
import
freemarker.template.TemplateException;
import
freemarker.template.TemplateNotFoundException;
/**
* PDF生成辅助类
* @author Goofy <a href="http://www.xdemo.org">http://www.xdemo.org</a>
*
*/
@SuppressWarnings
(
"deprecation"
)
public
class
PdfHelper {
public
static
ITextRenderer getRender()
throws
DocumentException, IOException {
ITextRenderer render =
new
ITextRenderer();
String path = getPath();
//添加字体,以支持中文
render.getFontResolver().addFont(path +
"resources/ARIALUNI.TTF"
, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
render.getFontResolver().addFont(path +
"resources/SIMSUN.TTC"
, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
return
render;
}
//获取要写入PDF的内容
public
static
String getPdfContent(String ftlPath, String ftlName, Object o)
throws
TemplateNotFoundException, MalformedTemplateNameException, ParseException, IOException, TemplateException {
return
useTemplate(ftlPath, ftlName, o);
}
//使用freemarker得到html内容
public
static
String useTemplate(String ftlPath, String ftlName, Object o)
throws
TemplateNotFoundException, MalformedTemplateNameException, ParseException, IOException, TemplateException {
String html =
null
;
Template tpl = getFreemarkerConfig(ftlPath).getTemplate(ftlName);
tpl.setEncoding(
"UTF-8"
);
StringWriter writer =
new
StringWriter();
tpl.process(o, writer);
writer.flush();
html = writer.toString();
return
html;
}
/**
* 获取Freemarker配置
* @param templatePath
* @return
* @throws IOException
*/
private
static
Configuration getFreemarkerConfig(String templatePath)
throws
IOException {
Configuration config =
new
Configuration();
config.setDirectoryForTemplateLoading(
new
File(templatePath));
config.setEncoding(Locale.CHINA,
"utf-8"
);
return
config;
}
/**
* 获取类路径
* @return
*/
public
static
String getPath(){
return
PdfHelper.
class
.getResource(
""
).getPath().substring(
1
);
}
}
|
模板文件
<!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
>
<
title
></
title
>
<
style
type
=
"text/css"
>
body {
margin-left: 45px;
margin-right: 45px;
font-family: Arial Unicode MS;
font-size: 10px;
}
table {
margin: auto;
width: 100%;
border-collapse: collapse;
border: 1px solid #444444;
}
th,td {
border: 1px solid #444444;
font-size: 10px;
margin-left: 5px;
}
.mcContent {
line-height: 180%;
padding: 20px;
}
.logo {
text-align: center;
}
.title {
text-align: center;
font-weight: bold;
font-size: 20px;
}
.notes {
font-weight: normal;
margin-left: 5px;
margin-right: 5px;
line-height: 18px;
}
.text_content {
margin-left: 5px;
margin-right: 5px;
line-height: 18px;
}
.sum_insured_first_row {
width: 20%;
}
.sum_insured_span {
font-size: 10px;
}
.special_agreements_div {
page-break-before: always;
font-size: 14px;
margin-top: 20px;
}
.special_agreements_div .special_agreements {
font-size: 18px;
font-weight: bold;
}
.title_right {
width: 100%;
margin: 0 auto;
}
.title_right p {
text-align: left;
margin: 0;
margin-left: 50%;
padding: 0;
}
@page {
size: 8.5in 11in;
@
bottom-center
{
content
:
"page "
counter(
page
)
" of "
counter(
pages
);
}
.signature {
margin: 0 auto;
clear: both;
font-size: 16px;
font-weight: bold;
}
.signature_table {
/* font-size: 16px; */
font-weight: bold;
}
</
style
>
</
head
>
<
body
>
作者:<
a
href
=
"http://www.xdemo.org/"
>http://www.xdemo.org/</
a
>
<
div
>
<
p
>你好:${name}</
p
>
<
div
class
=
"logo"
>
<!--这里的图片使用相对与ITextRenderer.getSharedContext().setBaseURL("file:/"+imageDiskPath);的路径-->
图片支持<
img
src
=
"logo1.png"
/>
</
div
>
<
div
>
<
p
>Hello PDF: 中文支持</
p
>
<
div
style
=
"border:1px solid red;color:red;"
>
样式支持,红边框,红字
</
div
>
<
div
style
=
"border:10px solid blue;color:blue;"
>
样式支持,蓝色10像素的边框,蓝字
</
div
>
<
hr
/>
<
table
>
<
tr
style
=
"background:gray;"
>
<
th
>A</
th
>
<
th
>B</
th
>
<
th
>C</
th
>
<
th
>D</
th
>
</
tr
>
<
tr
>
<
td
>100</
td
>
<
td
>29</
td
>
<
td
>32</
td
>
<
td
>43</
td
>
</
tr
>
<
tr
>
<
td
>100</
td
>
<
td
>29</
td
>
<
td
>32</
td
>
<
td
>43</
td
>
</
tr
>
<
tr
>
<
td
>100</
td
>
<
td
>29</
td
>
<
td
>32</
td
>
<
td
>43</
td
>
</
tr
>
<
tr
>
<
td
>100</
td
>
<
td
>29</
td
>
<
td
>32</
td
>
<
td
>43</
td
>
</
tr
>
<
tr
>
<
td
>100</
td
>
<
td
>29</
td
>
<
td
>32</
td
>
<
td
>43</
td
>
</
tr
>
</
table
>
</
div
>
</
div
>
</
body
>
</
html
>
|
注意
本 工具类提供了两种字体支持中文,所以定义样式的时候字体只能用:simsun或者arial unicode MS,否则中文显示不出来,如需其他字体另行添加),另外请注意图片的路径问题,html中z如果有图片,图片的路径则使用这里设置的路径的相对路径,这 个是作为根路径,如
<
div
class
=
"logo"
>
<!--这里的图片使用相对与ITextRenderer.getSharedContext().setBaseURL("file:/"+imageDiskPath);的路径-->
图片支持<
img
src
=
"logo1.png"
/>
</
div
>
|
如果需要PDF的下载,可以通过generateToServletOutputStream这个方法来获取PDF的输出流,然后通过response写到客户端去
转载请注明来源: http://www.xdemo.org/flying-saucer-html-freemarker-pdf/