本篇博客主要是爲了介紹如何使用:flying-saucer+itext+freemark實現導出複雜點的pdf文件。css
<dependency> <groupId>org.xhtmlrenderer</groupId> <artifactId>flying-saucer-pdf</artifactId> <version>9.1.5</version> </dependency>
搜索:simsun.ttc
宋體(對應css中的 屬性 font-family: SimSun; /宋體/)html
把這個模板放到
java
<?xml version="1.0" encoding="UTF-8"?> <!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" xml:lang="en" lang="en"> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> <title>准考證</title> <style> @page { size: 13.8in 10.4in; } </style> <!--@page { size: 13.8in 10.4in; } 這個能夠調整pdf頁面的大小很好用--> </head> <body> <div style="width: 1200px; margin:0 auto; background: #fff; position: relative"> <img src="/isuyang/images/steam/students.jpg" width="1200px;" alt=""/> <span style="color:#333; font-size:12.0pt; font-family: ; position: absolute; top: 63px; left:154px;">${certificateNumber}</span> <span style="color:#333; font-size:20.0pt; font-family: SimSun; font-weight: bold; position: absolute; top: 320px; left:236px;width: 160px; text-align: center">${realName}</span> <span style="color:#333; font-size:20.0pt; font-family: SimSun; font-weight: bold; position: absolute; top: 426px; left:236px;width: 140px; text-align: center">${division}</span> <span style="color:#333; font-size:20.0pt; font-family: SimSun; font-weight: bold; position: absolute; top: 426px; left:428px;width: 140px; text-align: center">${grade}</span> <span style="color:#333; font-size:20.0pt; font-family: SimSun; font-weight: bold; position: absolute; top: 426px; left:612px;width: 140px; text-align: center">${prize}</span> </div> </body> </html>
<dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.20</version> </dependency>
這個文件不必定非得放在這裏,只是maven項目約定資源文件的目錄是在這。
ftl的文件內容:web
classic_compatible=true ##若是變量爲null,轉化爲空字符串,好比作比較的時候按照空字符作比較 whitespace_stripping=true ##去掉多餘的空格,很是有用 ##模版更新事件,設置爲1秒,正式環境設置爲3600秒 #template_update_delay=3600 template_update_delay=1 ##模版更新時間,這裏配置是1秒更新一次,正式環境,模版不會改變,能夠將這個值設很大,提升效率 ##locale=zh_CN ##中國 default_encoding=utf-8 ##編碼utf8 url_escaping_charset=utf-8 ##url編碼utf8 date_format=yyyy-MM-dd ##顯示日期格式 time_format=HH:mm:ss ##顯示時間格式 datetime_format=yyyy-MM-dd HH:mm:ss ##顯示日期格式 number_format=0.###### ##數字顯示格式 boolean_format=是,否 ## boolean顯示格式 tag_syntax=auto_detect ##設置標籤類型 兩種:[] 和 <> 。[] 這種標記解析要快些
記得在spring-context.xml文件裏引用這個文件,
spring
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd" default-lazy-init="true"> <description>ftl Configuration</description> <!-- 加載配置屬性文件 --> <context:property-placeholder ignore-unresolvable="true" location="classpath:config/config.properties" /> <bean id="configuration" class="freemarker.template.Configuration"/> </beans>
/** * 啓動 * <p> * 應用的啓動入口 * * @author ZhuangJunxiang(529272571@qq.com) * @Date 2017年4月10日 */ @Component public class Setup implements ServletContextAware { @Override public void setServletContext(final ServletContext context) { WebApplicationContext act = ContextLoader.getCurrentWebApplicationContext(); Configuration ftlConf = (Configuration) act.getBean("configuration"); FtlUtil.initConfiguration(ftlConf, context, "/", "config/ftl.properties"); } }
/** * 下載初賽的pdf證書 * */ @Void //這個是自定義註解,能夠刪除 @RequestMapping @ResponseBody public void downloadChuSaiPrizePdf() { stemViewService.downloadPdf(); }
public void downloadPdf() { String pdfPath = generatorPdf(getSteamSignup(), "student.ftl"); boolean exist = FileUtil.isExist(pdfPath); if (!exist) { throw ExceptionUtil.bEx("PDF不存在"); } try { DownloadUtil.download(MvcUtil.getResponse(), pdfPath); } catch (Exception e) { e.printStackTrace(); } finally { FileUtil.deleteFile(pdfPath); } } /** * 生成pdf * * @param parameter * @return TODO(這裏描述每一個參數,若是有返回值描述返回值,若是有異常描述異常) */ public String generatorPdf(Map<String, Object> parameter, String ftlPath) { //Pdf的存放路徑:"G:\\pdf\\" 這裏的路徑我是經過配置獲取的 String pdfPath = pdfConfig.getValue("pdfPath") + parameter.get("certificateNumber") + ".pdf"; //字體的存放路徑 這裏也是經過配置獲取的:能夠寫:G:\\pdf\\simsun.ttc String font1 = pdfConfig.getValue("fontPath"); OutputStream os = null; try { os = new FileOutputStream(pdfPath); ITextRenderer renderer = new ITextRenderer(); ResourceLoaderUserAgent callback = new ResourceLoaderUserAgent(renderer.getOutputDevice()); renderer.getSharedContext().setUserAgentCallback(callback); callback.setSharedContext(renderer.getSharedContext()); //添加中文字體 renderer.getFontResolver().addFont(font1, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED); //這裏的ftl路徑存放在WEB-INF/steam/下 String repAfterHtml = FtlUtil.build(configuration, "steam/" + ftlPath, parameter); renderer.setDocumentFromString(repAfterHtml); // 解決圖片的相對路徑問題,這裏也能夠寫:http://localhost:8080/的形式 renderer.getSharedContext().setBaseURL("http://static.isuyang.cn/"); renderer.layout(); renderer.createPDF(os); os.close(); os = null; } catch (Exception ex) { ex.printStackTrace(); } finally { if (os != null) { try { os.close(); } catch (IOException e) { // ignore } } } return pdfPath; } /** * 資源加載代理 * */ private static class ResourceLoaderUserAgent extends ITextUserAgent { public ResourceLoaderUserAgent(ITextOutputDevice outputDevice) { super(outputDevice); } protected InputStream resolveAndOpenStream(String uri) { InputStream is = super.resolveAndOpenStream(uri); System.out.println("加載資源文件: " + uri); return is; } }
DownloadUtil.javaapi
package com.we.core.web.util; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import javax.servlet.http.HttpServletResponse; import com.we.core.common.util.ExceptionUtil; import com.we.core.common.util.FileUtil; /** * 下載方法 * @author lq * @Date 2014-7-15 */ public class DownloadUtil { public static HttpServletResponse download(final HttpServletResponse response, final String path) throws Exception { return download(response, path, null); } public static HttpServletResponse download(final HttpServletResponse response, final String path, final String fileName) throws Exception { File file = new File(path); String fn = fileName; if (com.we.core.common.util.Util.isEmpty(fileName)) { fn = file.getName(); } else { if (fileName.indexOf(".") == -1) { fn = fileName + "." + FileUtil.getSuffix(file.getName()); } } InputStream fis = new BufferedInputStream(new FileInputStream(path)); byte[] buffer = new byte[fis.available()]; fis.read(buffer); fis.close(); response.reset(); response.addHeader("Content-Disposition", "attachment;filename=" + new String(fn.getBytes("gb2312"), "ISO8859-1")); response.addHeader("Content-Length", "" + file.length()); OutputStream toClient = new BufferedOutputStream(response.getOutputStream()); response.setContentType("application/octet-stream"); toClient.write(buffer); toClient.flush(); toClient.close(); return response; } public static HttpServletResponse viewWord(final HttpServletResponse response, final String path) throws Exception { try { File file = new File(path); String filename = file.getName(); InputStream fis = new BufferedInputStream(new FileInputStream(path)); byte[] buffer = new byte[fis.available()]; fis.read(buffer); fis.close(); response.reset(); response.addHeader("Content-Disposition", "inline;filename=" + new String(filename.getBytes("gb2312"), "ISO8859-1")); OutputStream toClient = new BufferedOutputStream(response.getOutputStream()); response.setContentType("application/pdf"); toClient.write(buffer); toClient.flush(); toClient.close(); } catch (Exception e) { throw ExceptionUtil.bEx("文件損壞,預覽失敗"); } return response; } public HttpServletResponse viewTxt(final HttpServletResponse response, final String path) throws Exception { try { BufferedReader bis = null; File file = new File(path); InputStream in = new FileInputStream(file); bis = new BufferedReader(new InputStreamReader(in)); StringBuffer buf = new StringBuffer(); String temp; while ((temp = bis.readLine()) != null) { buf.append(temp); response.getWriter().write(temp); if (buf.length() >= 1000) { break; } } bis.close(); } catch (Exception e) { throw ExceptionUtil.bEx("文件損壞,預覽失敗"); } return response; } }
最好參考官方文檔,由於好多寫的都是不全,還有就是在搜索百度的時候必定要搜索博客靠前的文章,能夠使用百度的搜索工具過濾一下。
https://developers.itextpdf.com/examples/xml-worker-itext5/html-imagesapp