1、首先通过maven的pom.xml文件引入jar包
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.22</version>
</dependency>
<dependency>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>flying-saucer-pdf</artifactId>
<version>9.0.3</version>
</dependency>
2、
编写一个PDF生成辅助类
3.编写一个pdf工具类package com.bjb.test; 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; public class PdfHelper { public static ITextRenderer getRender() throws DocumentException, IOException { ITextRenderer render = new ITextRenderer(); String path = getPath(); //添加字体,以支持中文 render.getFontResolver().addFont(path + "com/bjb/ftl/arialuni.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED); render.getFontResolver().addFont(path + "com/bjb/ftl/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.setURLEscapingCharset("utf-8");; StringWriter writer = new StringWriter(); tpl.process(o, writer); writer.flush();
package com.bjb.test; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.util.ArrayList; import java.util.HashMap; import java.util.List; 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; public class PdfUtils { public static void main(String[] args) { try { Map<Object, Object> map=new HashMap<Object, Object>(); //存入一个集合 List<String> list = new ArrayList<String>(); list.add("小明"); list.add("张三"); list.add("李四"); list.add("王五"); map.put("name", "http://www.xdemo.org/"); map.put("nameList", list); String path=PdfHelper.getPath(); System.out.println(path); generateToFile(path, "com/bjb/ftl/tpl.ftl",path+"com/bjb/ftl/", map, "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; } }
html = writer.toString(); return html; } /** * 获取Freemarker配置 * @param templatePath * @return * @throws IOException */ private static Configuration getFreemarkerConfig(String templatePath) throws IOException { freemarker.template.Version version = new freemarker.template.Version("2.3.22"); Configuration config = new Configuration(version); 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); } }
package com.bjb.test;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
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;
public class PdfUtils {
public static void main(String[] args) {
try {
Map<Object, Object> map=new HashMap<Object, Object>();
//存入一个集合
List<String> list = new ArrayList<String>();
list.add("小明");
list.add("张三");
list.add("李四");
list.add("王五");
map.put("name", "http://www.xdemo.org/");
map.put("nameList", list);
String path=PdfHelper.getPath();
System.out.println(path);
generateToFile(path, "com/bjb/ftl/tpl.ftl",path+"com/bjb/ftl/", map, "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;
}
}
4.pdf生成模板(tpl.ftl)
<!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>
<tr>
<#list nameList as list>
<td>${list}</td>
</#list>
</tr>
</table>
</div>
</div>
</body>
</html>
5.字体
生成pdf工具类中使用了两种字体分别为arialuni.ttf和simsun.ttc,请大家自行到百度中搜索下载。