用到的几个JAR包,freemarker-2.3.20.jar、itext-2.0.8.jar、core-renderer-R5pre1.jar。这几个包中,只有freemarker-2.3.20.jar在maven中央仓库里有,其他两个是从网上其他人分享的。
怎么把第三方jar包导入Maven仓库,有百度经验写的不错,http://jingyan.baidu.com/article/64d05a025a936bde55f73b29.html
模板和字体放在/WEB-INF/下级目录下
/WEB-INF/templates/creditAgreementPDF.ftl
/WEB-INF/font/simsun.ttc
可以根据自己的情况更改文件存放位置。
怎么把第三方jar包导入Maven仓库,有百度经验写的不错,http://jingyan.baidu.com/article/64d05a025a936bde55f73b29.html
建议直接用已经调试好的这几个版本的配置,因为不同的版本之间,可能不兼容,比如itext高版本的包名都换了。
1、maven pom.xml配置
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.20</version>
</dependency>
<dependency>
<groupId>com.lowagie</groupId>
<artifactId>itext</artifactId>
<version>2.0.8</version>
</dependency>
<dependency>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>core-renderer</artifactId>
<version>R5pre1</version>
</dependency>
2、PDF工具类
/**
* PDF工具类
* @author LQX
*
*/
public class PDFUtil {
/**
* 生成PDF文件流
* @param request
* @param ftlName 文件名称
* @param root 数据
* @return ByteArrayOutputStream
* @throws Exception
*/
public static ByteArrayOutputStream createPDF(HttpServletRequest request, String ftlName, Object root) throws Exception {
String basePath = request.getSession().getServletContext().getRealPath("/");//绝对路径
Configuration cfg = new Configuration();
try {
cfg.setLocale(Locale.CHINA);
cfg.setEncoding(Locale.CHINA, "UTF-8");
//设置编码
cfg.setDefaultEncoding("UTF-8");
//设置模板路径
cfg.setDirectoryForTemplateLoading(new File(basePath + "/WEB-INF/templates/"));
//获取模板
Template template = cfg.getTemplate(ftlName);
template.setEncoding("UTF-8");
ITextRenderer iTextRenderer = new ITextRenderer();
//设置字体
ITextFontResolver fontResolver = iTextRenderer.getFontResolver();
fontResolver.addFont(basePath + "/WEB-INF/font/simsun.ttf", BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
Writer writer = new StringWriter();
//数据填充模板
template.process(root, writer);
//设置输出文件内容及路径
String str = writer.toString();
iTextRenderer.setDocumentFromString(str);
iTextRenderer.getSharedContext().setBaseURL("file:/home/ddcj/");//共享路径
iTextRenderer.layout();
//生成PDF
ByteArrayOutputStream baos = new ByteArrayOutputStream();
iTextRenderer.createPDF(baos);
baos.close();
return baos;
} catch(Exception e) {
throw new Exception(e);
}
}
}
3、spring MVC 相关类
@RequestMapping("creditAgreementPDFDownload")
@ResponseBody
public void creditAgreementPDFDownload(HttpServletRequest request, HttpServletResponse response) throws Exception {
//数据封装部分
Map map = new HashMap<String, String>();
map.put("test", "---中国---");
try {
ByteArrayOutputStream baos = PDFUtil.createPDF(request, "creditAgreementPDF.ftl", map);
System.out.println(baos);
//设置response文件头
renderPdf(response, baos.toByteArray(), "123");
} catch (Exception e) {
logger.error("create PDF file failure!!!");
throw new Exception(e);
}
}
调用renderPdf之前,已经生成pdf文件,此方法主要是设置文件头,并把文件作为附件下载。
public void renderPdf(HttpServletResponse response, final byte[] bytes, final String filename) {
initResponseHeader(response, PDF_TYPE);
setFileDownloadHeader(response, filename, ".pdf");
if (null != bytes) {
try {
response.getOutputStream().write(bytes);
response.getOutputStream().flush();
} catch (IOException e) {
throw new IllegalArgumentException(e);
}
}
}
设置响应头,主要设置字符编码和缓存即可。
/**
* 分析并设置contentType与headers.
*/
private HttpServletResponse initResponseHeader(HttpServletResponse response, final String contentType, final String... headers) {
// 分析headers参数
String encoding = DEFAULT_ENCODING;
boolean noCache = DEFAULT_NOCACHE;
for (String header : headers) {
String headerName = StringUtils.substringBefore(header, ":");
String headerValue = StringUtils.substringAfter(header, ":");
if (StringUtils.equalsIgnoreCase(headerName, HEADER_ENCODING)) {
encoding = headerValue;
} else if (StringUtils.equalsIgnoreCase(headerName, HEADER_NOCACHE)) {
noCache = Boolean.parseBoolean(headerValue);
} else {
throw new IllegalArgumentException(headerName + "不是一个合法的header类型");
}
}
// 设置headers参数
String fullContentType = contentType + ";charset=" + encoding;
response.setContentType(fullContentType);
if (noCache) {
// Http 1.0 header
response.setDateHeader("Expires", 0);
response.addHeader("Pragma", "no-cache");
// Http 1.1 header
response.setHeader("Cache-Control", "no-cache");
}
return response;
}
让文件作为附件下载
/**
* 设置让浏览器弹出下载对话框的Header.
* @param fileName下载后的文件名.
*/
public void setFileDownloadHeader(HttpServletResponse response, String fileName, String fileType) {
try {
// 中文文件名支持
String encodedfileName = new String(fileName.getBytes("GBK"), "ISO8859-1");
response.setHeader("Content-Disposition", "attachment; filename=\"" + encodedfileName + fileType + "\"");
} catch (UnsupportedEncodingException e) {
}
}
creditAgreementPDF.ftl
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>PDF下载</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style mce_bogus="1" type="text/css">
body {font-family: SimSun; background:none;margin-left: auto;margin-right: auto;}
body,html,div,p{ font-size:14px; margin:0px; padding:0px;}
</style>
</head>
<body>
<table width="100%" height="60" border="0" align="center" cellpadding="0" cellspacing="0">
<tr>
<td>12345</td>
<td>${test}</td>
<td>abc</td>
</tr>
</table>
</body>
</html>
我遇到的问题是中文一直不显示,查看各种资料没解决,最终尝试了别人写好的ftl文档,解决问题,除了java类之外,这个文件也会导致中文不显示,注意设置font-family:SimSun,这里java设置相同,用的是宋体。
模板和字体放在/WEB-INF/下级目录下
/WEB-INF/templates/creditAgreementPDF.ftl
/WEB-INF/font/simsun.ttc
可以根据自己的情况更改文件存放位置。
相关jar包资源:
http://download.csdn.net/detail/qingxiutianya/9582279