如何使用Java中的wkhtmlpdf将HTML文件转换为PDF

Sur*_*ati 9 java api wkhtmltopdf

我想使用HTML文件转换为PDF文件wkhtmltopdf.wkhtmltopdf对我来说是最好的选择,因为它使用WebKit呈现HTML文件.问题是我想使用Java做同样的事情但wkhtmltopdf不提供任何Java API.

我可以使用Runtime.exec()ProcessBuilder从Java派生一个新进程,并wkhtmtopdf在该进程中使用它创建PDF输出.但是,当我开发基于Web的应用程序时,我不允许在服务器中创建这么多新进程.

有什么其他办法让我可以使用wkhtmltopdf吗?我真的想用它,因为它给了我确切的输出.

或者,是否有任何其他开源浏览器引擎提供可以呈现我的HTML页面的Java API wkhtmltopdf

njf*_*ife 8

请记住,运行Java代码的系统必须安装wkhtmltopdf用于我在这里工作的任何内容...访问www.wkhtmltopdf.org并下载所需的版本.

我知道这已经过时了,到现在为止你已经想到了这一点,但如果你不想使用JNI或JNA这样做,你可以通过系统上的.exec调用来完成.

这是一个完全符合你想要的课程而不必大惊小怪JNI或JNA:

public class MegaSimplePdfGenerator {

    public void makeAPdf() throws InterruptedException, IOException {
        Process wkhtml; // Create uninitialized process
        String command = "wkhtmltopdf http://www.google.com /Users/Shared/output.pdf"; // Desired command

        wkhtml = Runtime.getRuntime().exec(command); // Start process
        IOUtils.copy(wkhtml.getErrorStream(), System.err); // Print output to console

        wkhtml.waitFor(); // Allow process to run
    }
}
Run Code Online (Sandbox Code Playgroud)

您必须以某种方式绑定到其中一个输入流以运行该进程.这可以是inputStream或errorStream.在这种情况下,因为我只是写入文件,所以我继续将System.err连接到wkhtml进程的errorStream.

如何只使用流!

如果您希望源HTML来自流和/或目标PDF要写入流,那么您将使用" - "作为"URI"而不是常规字符串.

示例:wkhtmltopdf - -wkhtmltopdf /Users/Shared/somefile.html -

然后,您可以捕获输入和输出流,并根据需要进行写入和读取.

如果您只连接到单个流,那么您不需要使用线程,并且您将无法获得流无休止地等待彼此的情况.

但是,如果您使用的是HTML源和PDF目标的流,那么您必须使用线程来完成该过程.

注意:请记住,必须为wkhtmltopdf刷新和关闭OutputStream才能开始构建PDF并传输结果!

例:

public class StreamBasedPdfGenerator {
  public void makeAPdfWithStreams() throws InterruptedException, IOException {
        Process wkhtml; // Create uninitialized process

        // Start by setting up file streams
        File destinationFile = new File("/Users/Shared/output.pdf");
        File sourceFile = new File("/Users/Shared/pdfPrintExample.html");

        FileInputStream fis = new FileInputStream(sourceFile);
        FileOutputStream fos = new FileOutputStream(destinationFile);

        String command = "wkhtmltopdf - -"; // Desired command

        wkhtml = Runtime.getRuntime().exec(command); // Start process

        Thread errThread = new Thread(() -> {
            try {
                IOUtils.copy(wkhtml.getErrorStream(), System.err);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        });
        Thread htmlReadThread = new Thread(() -> {
            try {
                IOUtils.copy(fis, wkhtml.getOutputStream());
                wkhtml.getOutputStream().flush();
                wkhtml.getOutputStream().close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        });
        Thread pdfWriteThread = new Thread(() -> {
            try {
                IOUtils.copy(wkhtml.getInputStream(), fos);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        });

        // Do NOT use Run... it should be clear why, you want them to all be going at the same time.
        errThread.start();
        pdfWriteThread.start();
        htmlReadThread.start();

         // Connect HTML Source Stream to wkhtmltopdf
         // Connect PDF Source Stream from wkhtmltopdf to the Destination file steam

        wkhtml.waitFor(); // Allow process to run
    }
}
Run Code Online (Sandbox Code Playgroud)

当您在Web服务器上运行此流并希望避免创建临时HTML或PDF文件时,流非常适合您,您可以通过捕获和写入HTTP响应流来简单地传回响应.

我希望这有助于某人!


Ben*_*kay 6

htmltopdf Java的一个尝试。它使用由 生成的本机库wkhtmltopdf,因此您应该期望通过对流程进行更多控制来获得相同的结果。

(我是这个库的作者)