我是不會告訴你,關注公衆號《andyqian》,回覆pdf,會給你整個工程代碼的!html
這是一篇之前的文章,最近作了優化處理,決定分享在這裏,沒有時間閱讀全文的童鞋,可直接拖到最後一章節。進入主題,今天介紹的是電子憑證(pdf)生成的解決方案,會從幾個經常使用的工具來介紹,也會對比一下幾者之間的性能。linux
在官網中 http://itextpdf.com/描述:windows
iText, the world's preferred PDF library,iText is a software developer toolkit that allows users to integrate PDF functionalities within their applications, processes or productsapp
iText,是世界上首選的PDF庫,iText是一個軟件開發人員工具包,容許用戶將PDF功能集成到其餘應用程序,流程或者產品中。 其特色有:maven
在使用iTex時,咱們須要添加Maven依賴,以下:ide
<dependency> <groupId>com.itextpdf</groupId> <artifactId>itextpdf</artifactId> <version>5.5.11</version> </dependency>
代碼:工具
/** * 生成pdf文件 */ @Test public void testCreatePdf(){ try{ // 1. new Document Document document = new Document(); PdfWriter.getInstance(document, new FileOutputStream(DEST)); // 2. 打開document document.open(); // 3. 添加內容 document.add(new Paragraph("hello world!")); // 4. 關閉 (若是未關閉則會生成無效的pdf文件) document.close(); }catch(DocumentException ex){ ex.printStackTrace(); }catch (FileNotFoundException ex){ ex.printStackTrace(); } }
效果:
性能
iText內置支持多種字體,咱們能夠經過FontFactory類找到iText的內置字體:字體
Courier; Courier-Bold; Courier-Oblique; Courier-BoldOblique; Helvetica; Helvetica-Bold; Helvetica-Oblique; Helvetica-BoldOblique; Symbol; Times; Times-Roman; Times-Bold; Times-Italic; Times-BoldItalic; ZapfDingbats;
一樣,iText也容許自定義字體,itext默認字體不支持中文,這時,咱們就能夠經過自定義字體來解決這個問題,代碼以下所示:優化
@Test public void testChineseFontPdf(){ try { //1. new document Document document = new Document(); PdfWriter.getInstance(document, new FileOutputStream("/tmp/pdf/2017/1.pdf")); //2. open document document.open(); BaseFont bf = BaseFont.createFont(path()+"fonts/SIMKAI.TTF", BaseFont.IDENTITY_H,BaseFont.EMBEDDED); //3. 註冊字體 Font font = new Font(bf,30); //3. 添加段落,並設置字體 document.add(new Paragraph("hello world(中文,)",font)); //4. close document document.close(); }catch(FileNotFoundException ex){ ex.printStackTrace(); }catch(DocumentException ex){ ex.printStackTrace(); }catch(IOException ex){ ex.printStackTrace(); } } /** * 獲取資源的路徑 * @return */ private String path(){ String path = this.getClass().getResource("/").getPath(); return path; }
效果以下:
一般咱們會在pdf文件中生成表格,來展現數據,在iText中也是很是方便的,代碼以下:
/** * 生成表格 */ @Test public void testTablePdf(){ try { //1.new document Document document = new Document(); PdfWriter.getInstance(document,new FileOutputStream("/tmp/pdf/2017/1.pdf")); //2 open document document.open(); //3.添加pdf tables 3表示列數, PdfPTable pdfPTable = new PdfPTable(3); // cell表示單元格,(12表示12個單元格,3列,12個單元格就造成來一個4行3列的表格) for (int i = 0; i < 12; i++) { pdfPTable.addCell("cell" + i); } document.add(pdfPTable); //4. 關閉document document.close(); }catch(DocumentException ex){ ex.printStackTrace(); }catch(FileNotFoundException ex){ ex.printStackTrace(); } }
生成效果以下所示:
代碼:
/** * 生成image */ @Test public void testImagePdf(){ try { //1.new document Document document = new Document(); PdfWriter.getInstance(document,new FileOutputStream("/tmp/pdf/2017/1.pdf")); //2 open document document.open(); document.add(new Paragraph("Hello world!")); //3.添加image Image image = Image.getInstance(path()+"/images/timg.jpg"); image.scaleAbsolute(PageSize.A4.rotate()); document.add(image); //4. 關閉document document.close(); }catch(DocumentException ex){ ex.printStackTrace(); }catch(FileNotFoundException ex){ ex.printStackTrace(); }catch (IOException ex){ ex.printStackTrace(); } }
效果:
咱們在實際項目中,須要將html格式的文檔轉換爲pdf工具,在iText中,默認是不直接支持html格式文檔的,咱們能夠藉助com.itextpdf.tool來生成 首先添加maven
<dependency> <groupId>com.itextpdf.tool</groupId> <artifactId>xmlworker</artifactId> <version>5.5.11</version> </dependency>
代碼以下所示:
/** * author: andy * date: 17-5-30 * blog: www.andyqian.com * version: 0.0.1 * description: 生成html格式內容的工具類 */ public class CreateHtmlPdfTest { /** * html內容路徑 */ private static final String HTML_PATH= "/html/helloworld.html"; private static final String FONT_PATH="/fonts/SIMKAI.TTF"; /** * 生成pdf格式的內容 */ @Test public void testHtml(){ try { //1. new document Document document = new Document(); PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("/tmp/pdf/2017/1.pdf")); //2.open document document.open(); //3. 設置字體 XMLWorkerFontProvider xmlWorkerFontProvider = new XMLWorkerFontProvider(XMLWorkerFontProvider.DONTLOOKFORFONTS); xmlWorkerFontProvider.register(getContextPath()+FONT_PATH); //4. 文件 FileInputStream fileInputStream = new FileInputStream(getContextPath()+HTML_PATH); XMLWorkerHelper.getInstance().parseXHtml(writer, document,fileInputStream, Charset.forName("UTF-8"),xmlWorkerFontProvider); //3. close document document.close(); }catch(Exception ex){ ex.printStackTrace(); } } /** * 獲取上下文路徑 * @return */ private String getContextPath(){ return this.getClass().getResource("/").getPath(); } }
html代碼內容:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"/> <title>標題</title> </head> <style> *{ font-family: KaiTi_GB2312; } </style> <body> hello world! XMLWorkerHelper [這是帶有中文的html格式內容] </body> </html>
代碼結構爲:
效果以下所示:
首先添加Freemarker Maven依賴以下所示:
<dependency> <groupId>org.freemarker</groupId> <artifactId>freemarker</artifactId> <version>2.3.23</version> </dependency>
代碼以下所示:
/** * author: andy * date: 17-5-30 * blog: www.andyqian.com * version: 0.0.1 * description: 經過feemarker工具類生成pdf */ public class CreateFeemarkerPdfTest { private static final String FONT_PATH="/fonts/SIMKAI.TTF"; private static final String HTML_PATH="/html/feemarker.html"; @Test public void testCreatePdf(){ try { //1. new document Document document = new Document(); PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream("/tmp/pdf/2017/1.pdf")); //2.open document document.open(); //3. 設置字體 XMLWorkerFontProvider xmlWorkerFontProvider = new XMLWorkerFontProvider(XMLWorkerFontProvider.DONTLOOKFORFONTS); xmlWorkerFontProvider.register(getContextPath()+FONT_PATH); //4. 設置模板內容 Map<String,Object> params = new HashMap<String,Object>(); params.put("name","鞠騫"); params.put("career","軟件開發"); params.put("blog","http://www.andyqian.com"); String content = getFreeMarkerText(htmlContent(),params); //4. 文件 InputStream inputStream = new ByteArrayInputStream(content.getBytes("utf-8")); XMLWorkerHelper.getInstance().parseXHtml(writer, document,inputStream, Charset.forName("UTF-8"),xmlWorkerFontProvider); //3. close document document.close(); }catch(Exception ex){ ex.printStackTrace(); } } /** * 獲取上下文路徑 * @return */ private String getContextPath(){ return this.getClass().getResource("/").getPath(); } /** * freemarker模板方法 * @param templateTxt 模板文本 * @param map 模板參數 * @return * @throws Exception */ public static String getFreeMarkerText(String templateTxt, Map<String, Object> map) throws Exception { String result = null; Configuration config = new Configuration(Configuration.VERSION_2_3_23); try { StringTemplateLoader e = new StringTemplateLoader(); e.putTemplate("t", templateTxt); config.setTemplateLoader(e); config.setDefaultEncoding("UTF-8"); Template template = config.getTemplate("t", "UTF-8"); StringWriter out = new StringWriter(); template.process(map, out); result = out.toString(); return result; } catch (IOException iex) { throw new Exception("獲取freemark模版出錯", iex); } catch (TemplateException ex) { throw new Exception("freemark模版處理異常", ex); } } /** * 獲取html內容 * @return */ private String htmlContent(){ String result = ""; try { FileInputStream fileInputStream = new FileInputStream(getContextPath() + HTML_PATH); int len=0; byte[] array = new byte[1024]; StringBuffer stringBuffer = new StringBuffer(); while((len=fileInputStream.read(array))!=-1){ stringBuffer.append(new String(array,0,len)); } result = stringBuffer.toString(); }catch(Exception ex){ ex.printStackTrace(); } return result; } }
效果以下:
其實上面,在windows平臺下仍是有些問題的,字體路徑會加載不到,處理方案,請看下一章節。
我是不會告訴你,關注公衆號《andyqian》,回覆pdf,會給你整個工程代碼的!
若是想拷貝代碼直接使用,也可使用下面代碼
public class PdfUtils { private static final Logger logger = LoggerFactory.getLogger(PdfUtils.class); /** * 經過html生成文件 * @param htmlContent html格式內容 * @param file 輸出文件file */ public static void createdPdfByItextHtml(String htmlContent,File file){ InputStream inputStream = null; FileOutputStream outputStream = null; PdfWriter writer = null; try { // 1. 獲取生成pdf的html內容 inputStream= new ByteArrayInputStream(htmlContent.getBytes("utf-8")); outputStream = new FileOutputStream(file); Document document = new Document(); writer = PdfWriter.getInstance(document, outputStream); document.open(); // 2. 添加字體 XMLWorkerFontProvider fontImp = new XMLWorkerFontProvider(XMLWorkerFontProvider.DONTLOOKFORFONTS); fontImp.register(getFontPath()); // 3. 設置編碼 XMLWorkerHelper.getInstance().parseXHtml(writer, document, inputStream, Charset.forName("UTF-8"),fontImp); // 4. 關閉,(不關閉則會生成無效pdf) document.close(); } catch (Exception ex) { ex.printStackTrace(); }finally { try { if(writer!=null){ writer.close(); } if (outputStream != null) { outputStream.close(); } if (inputStream != null) { inputStream.close(); } }catch(IOException ex){ ex.printStackTrace(); } } } /** * 應用場景: * 1.在windows下,使用Thread.currentThread()獲取路徑時,出現空對象,致使不能使用 * 2.在linux下,使用PdfUtils.class獲取路徑爲null, * 獲取字體路徑 * @return */ private static String getFontPath(){ String path=""; // 1. ClassLoader classLoader= Thread.currentThread().getContextClassLoader(); URL url = (classLoader==null)?null:classLoader.getResource("/"); String threadCurrentPath = (url==null)?"":url.getPath(); // 2. 若是線程獲取爲null,則使用當前PdfUtils.class加載路徑 if(StringUtil.isBlank(threadCurrentPath)){ path = PdfUtils.class.getClass().getResource("/").getPath(); } // 3.拼接字體路徑 StringBuffer stringBuffer = new StringBuffer(path); stringBuffer.append("/fonts/SIMKAI.TTF"); path = stringBuffer.toString(); logger.info("getFontPath threadCurrentPath: {} path: {}",threadCurrentPath,path); return path; }
上面getFontPath()方法中,對linux以及windows平臺作了字體加載路徑作了兼容處理。
本文從iText最基本的用法,分別介紹從表格,圖片,HTML,Feemarker來介紹iText,但願可以幫助到你。
有任何問題,均可以在公衆號下留言哦,在線提供幫助!
掃碼關注,一塊兒進步
我的博客: http://www.andyqian.com