Java實現Html轉PDF
阿新 • • 發佈:2018-12-30
專案上的客戶提出一個需求,把政務流程中的表單資料匯出成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工具類,方便呼叫。
- import java.io.File;
-
publicclass HtmlToPdf {
- //wkhtmltopdf在系統中的路徑
- privatestaticfinal String toPdfTool = "c:\\wkhtmltopdf.exe";
- /**
- * html轉pdf
- * @param srcPath html路徑,可以是硬碟上的路徑,也可以是網路路徑
- * @param destPath pdf儲存路徑
- * @return 轉換成功返回true
- */
- publicstaticboolean convert(String srcPath, String destPath){
-
File file = new
- File parent = file.getParentFile();
- //如果pdf儲存路徑不存在,則建立路徑
- if(!parent.exists()){
- parent.mkdirs();
- }
- StringBuilder cmd = new StringBuilder();
- cmd.append(toPdfTool);
- cmd.append(" ");
- cmd.append(srcPath);
- cmd.append(" ");
- cmd.append(destPath);
- boolean result = true;
- try{
- Process proc = Runtime.getRuntime().exec(cmd.toString());
- HtmlToPdfInterceptor error = new HtmlToPdfInterceptor(proc.getErrorStream());
- HtmlToPdfInterceptor output = new HtmlToPdfInterceptor(proc.getInputStream());
- error.start();
- output.start();
- proc.waitFor();
- }catch(Exception e){
- result = false;
- e.printStackTrace();
- }
- return result;
- }
- }
接收Process的輸入和錯誤資訊時,需要建立另外的執行緒,否則當前執行緒會一直等待(在Tomcat中有這種現象)。
- import java.io.BufferedReader;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.InputStreamReader;
- /**
- * 當java呼叫wkhtmltopdf時,用於獲取wkhtmltopdf返回的內容
- */
- publicclass HtmlToPdfInterceptor extends Thread {
- private InputStream is;
- public HtmlToPdfInterceptor(InputStream is){
- this.is = is;
- }
- publicvoid run(){
- try{
- InputStreamReader isr = new InputStreamReader(is, "utf-8");
- BufferedReader br = new BufferedReader(isr);
- String line = null;
- while ((line = br.readLine()) != null) {
- System.outlprintln(line.toString()); //輸出內容
- }
- }catch (IOException e){
- e.printStackTrace();
- }
- }
- }
在Servlet中呼叫
- /**
- * Html轉PDF
- */
- @WebServlet("/htmltopdf/servlet")
- publicclass HtmlToPdfServlet extends HttpServlet {
- privatestaticfinallong serialVersionUID = 1L;
- /**
- * Servlet接收引數path,獲取html的url
- */
- protectedvoid service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
- String path = request.getParameter("path");
- if(path == null || path.equals("")){
- return;
- }
- //獲取pdf的臨時儲存路徑
- //tmp為網站下的目錄
- //把生成的pdf放到網站下以便下載
- String pdfPath = request.getSession().getServletContext().getRealPath("/tmp");
- String pdfName = UUID.randomUUID().toString() + ".pdf";
- if(HtmlToPdf.convert(path, pdfPath + "/" + pdfName)){
- response.sendRedirect(request.getContextPath() + "/tmp/" + pdfName);
- }
- }
- }
在瀏覽器中輸入http://<網站路徑>/htmltopdf/servlet?path=http://blog.csdn.net