freemarker(ftl模板) + itext + spring 做PDF下载

用到的几个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 

建议直接用已经调试好的这几个版本的配置,因为不同的版本之间,可能不兼容,比如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


评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值