項目上的客戶提出一個需求,把政務流程中的表單數據導出成pdf或者圖片格式,用來作電子檔案材料。表單基於公司的電子政務構建平臺實現,在數據庫保存的都是html格式,因此打算直接把表單html轉成pdf或者圖片。由於表單是已經寫好了html頁面,那我要做的就是能完美解析html+css的pdf生成工具。在百度上搜索html轉pdf的結果,大部分都是用itext,itext的確是java開源組件的第一選擇。不過itext也有侷限,就是要自己寫模版,系統中的表單數量有好幾百個,爲每個表單做一個導出模版不現實。
最後,wkhtmltopdf進入了我的選擇範圍。wkhtmltopdf是一個使用webkit網頁渲染引擎開發的用來將 html轉成 pdf的工具,可以跟多種腳本語言進行集成來轉換文檔。
github地址 https://github.com/wkhtmltopdf/wkhtmltopdf
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;
- public class HtmlToPdf {
- //wkhtmltopdf在系統中的路徑
- private static final String toPdfTool = "c:\\wkhtmltopdf.exe";
- /**
- * html轉pdf
- * @param srcPath html路徑,可以是硬盤上的路徑,也可以是網絡路徑
- * @param destPath pdf保存路徑
- * @return 轉換成功返回true
- */
- public static boolean convert(String srcPath, String destPath){
- File file = new File(destPath);
- 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返回的內容
- */
- public class HtmlToPdfInterceptor extends Thread {
- private InputStream is;
- public HtmlToPdfInterceptor(InputStream is){
- this.is = is;
- }
- public void 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")
- public class HtmlToPdfServlet extends HttpServlet {
- private static final long serialVersionUID = 1L;
- /**
- * Servlet接收參數path,獲取html的url
- */
- protected void 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