依赖:
<dependency>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>flying-saucer-pdf</artifactId>
<version>9.1.18</version>
</dependency>
中文转换工具和模板目录:
转换工具下载链接:https://pan.baidu.com/s/1Y83-8TmETRhOUSJ_QyKgfg 密码:gqw0
工具类:
import com.lowagie.text.DocumentException;
import com.lowagie.text.pdf.BaseFont;
import freemarker.core.ParseException;
import freemarker.template.*;
import org.xhtmlrenderer.pdf.ITextRenderer;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.*;
@SuppressWarnings("deprecation")
public class PdfUtils {
public static ITextRenderer getRender() throws DocumentException, IOException {
ITextRenderer render = new ITextRenderer();
String path = getPath();
//添加字体,以支持中文
render.getFontResolver().addFont(path + "pdf/arialuni.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
render.getFontResolver().addFont(path + "pdf/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 {
Version version = new Version("2.3.25");
Configuration config = new Configuration(version);
config.setDirectoryForTemplateLoading(new File(templatePath));
config.setEncoding(Locale.CHINA, "utf-8");
return config;
}
/**
* 获取类路径
* @return
*/
public static String getPath(){
// return "/"+ PdfUtils.class.getResource("/").getPath().substring(1);
return PdfUtils.class.getResource("/").getPath();
}
/**
* 生成PDF到文件
* @param ftlPath 模板文件路径(不含文件名)
* @param ftlName 模板文件名(不含路径)
* @param data 数据
* @param outputFile 目标文件(全路径名称)
* @throws Exception
*/
public static void generateToFile(String ftlPath,String ftlName,Object data,String outputFile) throws Exception {
String html= getPdfContent(ftlPath, ftlName, data);
OutputStream out = null;
ITextRenderer render = null;
out = new FileOutputStream(outputFile);
render = getRender();
render.setDocumentFromString(html);
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,String title, HttpServletResponse response) throws TemplateNotFoundException, MalformedTemplateNameException, ParseException, IOException, TemplateException, DocumentException{
String html=getPdfContent(ftlPath, ftlName, data);
String outName = title+".pdf";
OutputStream out = null;
ITextRenderer render = null;
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "attachment; filename="+new String(outName.getBytes("UTF-8"), "ISO8859-1"));
out = response.getOutputStream();
render = 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;
}
}
测试:
public static void main(String[] args) {
try {
Map<Object, Object> o=new HashMap<Object, Object>();
//存入一个集合
List<String> list = new ArrayList<String>();
list.add("xiaoming");
list.add("张三");
list.add("李四");
o.put("name", "my name is rose");
o.put("nameList", list);
list.forEach(System.out::println);
String path = getPath();
generateToFile(path, "tpl2.ftl", o, "/Users/json/个人文稿/开发/191120-cpr/模版/xdemo.pdf");
} catch (Exception e) {
e.printStackTrace();
}
System.out.println(getPath());
}
模板文件:
<!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>
<meta charset="utf-8" />
<title>
</title>
<style>
/*解决html转pdf文件中文不显示的问题*/
body {
font-family: SimSun;
}
</style>
</head>
<body>
<#list cprMap as list>
<#if list['cpr1'].studentName??>
${list['cpr1'].studentName!""}
${list['cpr1'].courseDate!""}
</#if>
</#list>
</body>
</html>