1. 程式人生 > >Java實現Html轉PDF

Java實現Html轉PDF

專案上的客戶提出一個需求,把政務流程中的表單資料匯出成pdf或者圖片格式,用來作電子檔案材料。表單基於公司的電子政務構建平臺實現,在資料庫儲存的都是html格式,因此打算直接把表單html轉成pdf或者圖片。由於表單是已經寫好了html頁面,那我要做的就是能完美解析html+css的pdf生成工具。在百度上搜索html轉pdf的結果,大部分都是用itext,itext的確是java開源元件的第一選擇。不過itext也有侷限,就是要自己寫模版,系統中的表單數量有好幾百個,為每個表單做一個匯出模版不現實。 

最後,wkhtmltopdf進入了我的選擇範圍。wkhtmltopdf是一個使用webkit網頁渲染引擎開發的用來將 html轉成 pdf的工具,可以跟多種指令碼語言進行整合來轉換文件。

wkhtmltopdf把html轉成pdf很簡單,只要在windows命令列中輸入

c:\wkhtmltopdf.exe http://www.csdn.net c:\csdn.pdf

就可以把csdn網頁轉成pdf,並儲存到C盤根目錄。

在java中呼叫wkhtmltopdf的命令Runtime.getRuntime().exec("c:\wkhtmltopdf.exe http://www.csdn.net c:\csdn.pdf")就可以實現轉換。

下面把命令封裝成java工具類,方便呼叫。

  1. import java.io.File;  
  2. publicclass HtmlToPdf {  
  3.     //wkhtmltopdf在系統中的路徑
  4.     privatestaticfinal String toPdfTool = "c:\\wkhtmltopdf.exe";  
  5.     /** 
  6.      * html轉pdf 
  7.      * @param srcPath html路徑,可以是硬碟上的路徑,也可以是網路路徑 
  8.      * @param destPath pdf儲存路徑 
  9.      * @return 轉換成功返回true 
  10.      */
  11.     publicstaticboolean convert(String srcPath, String destPath){  
  12.         File file = new
     File(destPath);  
  13.         File parent = file.getParentFile();  
  14.         //如果pdf儲存路徑不存在,則建立路徑
  15.         if(!parent.exists()){  
  16.             parent.mkdirs();  
  17.         }  
  18.         StringBuilder cmd = new StringBuilder();  
  19.         cmd.append(toPdfTool);  
  20.         cmd.append(" ");  
  21.         cmd.append(srcPath);  
  22.         cmd.append(" ");  
  23.         cmd.append(destPath);  
  24.         boolean result = true;  
  25.         try{  
  26.             Process proc = Runtime.getRuntime().exec(cmd.toString());  
  27.             HtmlToPdfInterceptor error = new HtmlToPdfInterceptor(proc.getErrorStream());  
  28.             HtmlToPdfInterceptor output = new HtmlToPdfInterceptor(proc.getInputStream());  
  29.             error.start();  
  30.             output.start();  
  31.             proc.waitFor();  
  32.         }catch(Exception e){  
  33.             result = false;  
  34.             e.printStackTrace();  
  35.         }  
  36.         return result;  
  37.     }  
  38. }  

接收Process的輸入和錯誤資訊時,需要建立另外的執行緒,否則當前執行緒會一直等待(在Tomcat中有這種現象)。
  1. import java.io.BufferedReader;  
  2. import java.io.IOException;  
  3. import java.io.InputStream;  
  4. import java.io.InputStreamReader;  
  5. /** 
  6.  * 當java呼叫wkhtmltopdf時,用於獲取wkhtmltopdf返回的內容 
  7.  */
  8. publicclass HtmlToPdfInterceptor extends Thread {  
  9.     private InputStream is;  
  10.     public HtmlToPdfInterceptor(InputStream is){  
  11.         this.is = is;  
  12.     }  
  13.     publicvoid run(){  
  14.         try{  
  15.             InputStreamReader isr = new InputStreamReader(is, "utf-8");  
  16.             BufferedReader br = new BufferedReader(isr);  
  17.             String line = null;  
  18.             while ((line = br.readLine()) != null) {  
  19.                 System.outlprintln(line.toString()); //輸出內容
  20.             }  
  21.         }catch (IOException e){  
  22.             e.printStackTrace();  
  23.         }  
  24.     }  
  25. }  

在Servlet中呼叫
  1. /** 
  2.  * Html轉PDF 
  3.  */
  4. @WebServlet("/htmltopdf/servlet")  
  5. publicclass HtmlToPdfServlet extends HttpServlet {  
  6.     privatestaticfinallong serialVersionUID = 1L;  
  7.     /** 
  8.      * Servlet接收引數path,獲取html的url 
  9.      */
  10.     protectedvoid service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {  
  11.         String path = request.getParameter("path");  
  12.         if(path == null || path.equals("")){  
  13.             return;  
  14.         }  
  15.         //獲取pdf的臨時儲存路徑
  16.         //tmp為網站下的目錄
  17.         //把生成的pdf放到網站下以便下載
  18.         String pdfPath = request.getSession().getServletContext().getRealPath("/tmp");  
  19.         String pdfName = UUID.randomUUID().toString() + ".pdf";  
  20.         if(HtmlToPdf.convert(path, pdfPath + "/" + pdfName)){  
  21.             response.sendRedirect(request.getContextPath() + "/tmp/" + pdfName);  
  22.         }  
  23.     }  
  24. }  

在瀏覽器中輸入http://<網站路徑>/htmltopdf/servlet?path=http://blog.csdn.net