1、maven依賴
<dependency>
<groupId>com.itextpdf</groupId>
<artifactId>itextpdf</artifactId>
<version>5.4.2</version>
</dependency>
<dependency>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>core-renderer</artifactId>
<version>R8</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-io</artifactId>
<version>1.3.2</version>
</dependency>
2、controller
@RequestMapping(value = "projectExport", method = RequestMethod.GET)
public void projectExport(HttpServletRequest request, HttpServletResponse response) {
try {
Map map=new HashMap<String,Object>();
map.put("test","測試");
ByteArrayOutputStream baos = PDFUtil.createPDF("templates/project.html", map);
//設置response文件頭
PDFUtil.renderPdf(response, baos.toByteArray(), "pdf文件");
baos.close();
} catch (Exception e) {
logger.info("導出報錯",e);
}
}
3、PDFUtil
import com.itextpdf.text.pdf.BaseFont;
import freemarker.template.Configuration;
import freemarker.template.Template;
import org.apache.commons.io.output.ByteArrayOutputStream;
import org.apache.commons.lang.StringUtils;
import org.xhtmlrenderer.pdf.ITextFontResolver;
import org.xhtmlrenderer.pdf.ITextRenderer;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.Locale;
/**
* PDF工具類
* @author LQX
*
*/
public class PDFUtil {
private static String DEFAULT_ENCODING="utf-8";
private static String PDF_TYPE="application/pdf";
private static boolean DEFAULT_NOCACHE=true;
private static String HEADER_ENCODING="utf-8";
private static String HEADER_NOCACHE="no-cache";
/**
* 生成PDF文件流
* @param ftlName 文件名稱
* @param root 數據
* @return ByteArrayOutputStream
* @throws Exception
*/
public static ByteArrayOutputStream createPDF(String ftlName, Object root) throws Exception {
//相對路徑
File file = new File(PDFUtil.class.getResource("/").getPath());
Configuration cfg = new Configuration();
try {
cfg.setLocale(Locale.CHINA);
cfg.setEncoding(Locale.CHINA, "UTF-8");
//設置編碼
cfg.setDefaultEncoding("UTF-8");
//設置模板路徑
cfg.setDirectoryForTemplateLoading(file);
//獲取模板
Template template = cfg.getTemplate(ftlName);
template.setEncoding("UTF-8");
ITextRenderer iTextRenderer = new ITextRenderer();
//設置字體
ITextFontResolver fontResolver = iTextRenderer.getFontResolver();
fontResolver.addFont(file.getPath() + "/public/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("");//共享路徑*/
iTextRenderer.layout();
//生成PDF
ByteArrayOutputStream baos = new ByteArrayOutputStream();
iTextRenderer.createPDF(baos);
baos.close();
return baos;
} catch(Exception e) {
throw new Exception(e);
}
}
public static 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 static 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
*/
public static 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) {
}
}
}
3、project.html
<!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; }
@page {size: 800mm 400mm}
</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>
需要注意的點:
(1)、中文字體
html中要將body標簽的字體設置為SimSun,然后項目中要放這個字體文件,因為服務器中通常沒有這個文件,simsun.ttf字體百度上都可以下載。只有設置了字體后html中的中文才能識別出來。
(2)、css文件
如果你想導的pdf文件的樣式是css渲染后的頁面樣式,一定要注意link中css引用的路徑,通常用服務器的絕對路徑,你也可以自己換一換路徑試試。導出時會因為一些外部的文件的路徑寫的不對而出現空指針異常,可以先把這些都注釋掉再調試。
(3)、html標簽
這個工具導出的時候對html標簽的要求比較的嚴格,比如一些閉合標簽一定要寫完整,href鏈接中直接請求接口帶參數的時候有&連接的時候要在&后面加上amp;
(4)、pdf文件的大小
給這個html文件加上css樣式@page {size:800mm 400mm}這個樣式可以調整pdf的文件,因為我導出的時候寬度達不到我想要的寬度,但是我還是不會動態的去設置這個大小,歡迎知道的小伙伴指教。
————————————————
原文鏈接:https://blog.csdn.net/haha_66666/article/details/83025919