我想使用wkhtmltopdf
将HTML文件转换为PDF文件。 wkhtmltopdf
对我来说是最好的选择,因为它使用 WebKit 呈现HTML文件。问题是我想使用Java做同样的事情,但wkhtmltopdf
不提供任何Java API。
我可以使用Runtime.exec()
或ProcessBuilder
从Java派生新进程,并在该进程中使用wkhtmtopdf
创建PDF输出。但是,当我开发基于Web的应用程序时,我不允许在服务器中创建这么多新进程。
还有其他方法可以使用wkhtmltopdf
吗?我真的想用它,因为它给了我确切的输出。
或者,是否有其他开源浏览器引擎提供可以像wkhtmltopdf
一样呈现我的HTML页面的Java API?
答案 0 :(得分:7)
请记住,运行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
}
}
您必须以某种方式绑定到其中一个输入流,以便运行该进程。这可以是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
}
}
Streams很适合在Web服务器上运行它并且想要避免创建临时HTML或PDF文件时,您可以通过捕获并写入HTTP响应流来简单地传回响应。
我希望这有助于某人!
答案 1 :(得分:2)
尝试htmltopdf-java。它使用由wkhtmltopdf
生成的本机库,因此您应该期望获得相同的结果,并对流进行更多控制。
(我是这个图书馆的作者)
答案 2 :(得分:1)
wkhtmltopdf有C API。然后,您可以使用JNI进行Java到C的通信。
编辑:还有一个Java包装器:wkhtmltopdf-wrapper。