2014-06-18 3 views
4

CentOS OS에서 java ProcessBuilder를 통해 wkhtmltopdf를 호출하여 웹 페이지에서 pdf를 생성하려고합니다. 내가 인수를 인쇄하는 방법을 포함 시켰습니다Java ProcessBuilder가 wkhtmltopdf와 함께 작동하지 않습니다.

Command has terminated with status: 139 
Output: 

Error: Loading pages (1/6) .... 

및 빈 pdf 파일 (크기 0B)

를 만듭니다 문제는 내가 주요 방법으로 간단한 클래스를 실행할 때 프로세스에 종료 것입니다 클래스에서 wkhtmltopdf를 호출하고 명령을 복사하여 bash에서 실행하면 pdf가 만들어집니다. 더 자세히 : 윈도우에서 똑같은 클래스를 실행할 때 잘 동작합니다. 이 오류 코드 139의 원인은 무엇입니까? 그것은 wkhtmltopdf의 버그 일 수 있습니까 아니면 내가 잘못하고있는거야?

는 여기에 몇 가지 추가 정보입니다 :

OS :

/root/wk/wkhtmltox/bin/wkhtmltopdf --window-status export-ready 
    --encoding UTF-8 
    --custom-header username username 
    --custom-header password pass 
    --run-script "<some correctly escaped js>" 
    http://xx.xx.xx.xx/url?param1=1&param2=2 
    /root/sandbox/test.pdf 

코드 PDF 생성을위한 :

public String exportToPdf(final String bookmarkableUrl) { 
    String uuid = UUID.randomUUID().toString(); 

    final String fullUrl = "http://" + hostName + ":" + port + bookmarkableUrl; 

    // .html extension at the end is very important - wkhtmltopdf won't read 
    // the file if not there 
    String generatedPdfPath = tempDirPath + "/EMF/" + uuid; 
    try { 
     ProcessBuilder processBuilder = new ProcessBuilder(); 
     processBuilder.command(prepareCommandArguments(fullUrl, generatedPdfPath + PDF_FILE_EXTENSION)); 
     Process start = processBuilder.start(); 
     // One has to handle the error stream 
     handleStream(start.getErrorStream()); 
     handleStream(start.getInputStream()); 
     // Wait until process is executed. 
     start.waitFor(); 
    } catch (IOException | InterruptedException e) { 
     throw new RuntimeException("Error while generating PDF", e); 
    } 
    return generatedPdfPath; 
} 
내가 프로세스 빌더 실행하려고

[[email protected] sandbox]# uname -a 
Linux xxxxxx.com 2.6.32-279.22.1.el6.x86_64 #1 SMP Wed Feb 6 03:10:46 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux 

[[email protected] bin]# ./wkhtmltopdf --version 
Name: 
    wkhtmltopdf 0.12.0 03c001de254b857f08eba80b62d4b6490ffed41d 

명령

편집 :

private List<String> prepareCommandArguments(String inputUrl, String outputUrl) { 
    List<String> arguments = new ArrayList<>(15); 
    // absolute path to the wkhtmltopdf executable 
    arguments.add(wkhtmltopdfLocation); 
    // Wait until window.status is equal to this string before rendering page 
    arguments.add("--window-status"); 
    arguments.add("export-ready"); 
    // Set the default text encoding, for input 
    arguments.add("--encoding"); 
    arguments.add("UTF-8"); 
    // Set an additional HTTP header for system username 
    arguments.add("--custom-header"); 
    arguments.add("username"); 
    arguments.add(exportUsername); 
    // Set an additional HTTP header for system user password 
    arguments.add("--custom-header"); 
    arguments.add("password"); 
    arguments.add(exportPassword); 
    // Run this additional javascript after the page is done loading 
    // Used to remove irrelevant divisions and spanning of 
    // the html page, leaving only the print preview of the document 
    arguments.add("--run-script"); 
    arguments.add(getScriptFromFile(jsFilePath)); 
    // Bookmarkable url of the document 
    arguments.add(inputUrl);  
    // Path to the generated pdf 
    arguments.add(outputUrl); 
    return arguments; 
} 

단지 Process.Start를() 전에서 System.out.println (processBuilder.command())의 출력 :

내가 명령 인수 목록을 만드는 데 사용하는 코드를 추가
/root/wk/wkhtmltox/bin/wkhtmltopdf, --window-status, export-ready, --encoding, UTF-8, --custom-header, username, admin, --custom-header, password, admin, --run-script, "\$('.idoc-comments-column').remove(); \$('.idoc-left-column').remove(); \$('.idoc-left-column').remove(); \$('#topHeader').remove(); \$('#header').remove(); \$('.tree-header.breadcrumb_header').remove(); \$('.idoc-middle-column.pull-left.idoc-first-row').remove(); \$('.idoc-middle-column.pull-left').remove(); \$('.pull-left.text-center').remove(); \$('html').addClass('print-override-overflow'); \$('.idoc-editor').css('width', '80%'); \$('.idoc-editor').css('font-size', '14px'); \$('.idoc-editor').css('max-width', 'none'); \$('.idoc-editor').css('margin-left', '10%'); \$('.idoc-editor').css('margin-right', '10%'); \$('.idoc-editor').css('margin-top', '5%'); \$('.idoc-editor').css('margin-bottom', '5%');", http://xx.xx.xx.xx:xxxx/url/page.jsf?param1=1&param2=2, /root/sandbox/file.pdf 
+0

'prepareCommandArguments' 코드를 보여줄 수 있습니까? – A4L

+0

@ A4L 코드를 추가했습니다. 특별한 것은 없지만 목록에있는 args를 추가하면 입니다. – Ivo

+1

'getScriptFromFile' 메서드는 큰 따옴표로 묶인 문자열을 반환합니다. 그리고 스크립트 파일 자체에 이중 따옴표가 없으므로 바깥 쪽 큰 따옴표가 중간에 끝날 수도 있습니다. – shazin

답변

3

ProcessBuilder으로 쉘 - 이스 케이 핑을 수행 할 필요가 없습니다. 달러 기호를 이스케이프 처리하지 않고 JS 코드를 그대로 전달하고 큰 따옴표를 사용해보십시오.