Wkhtmltopdf是什么?引用官网的一句话:
wkhtmltopdf and wkhtmltoimage are open source (LGPLv3) command line tools to render HTML into PDF and various image formats using the Qt WebKit rendering engine. These run entirely “headless” and do not require a display or display service.
为什么要用这个工具?
项目需要每个月自动在后台生成PDF报告存储到文件服务器,不能使用前端生成PDF的方法,所以找到了这个工具。
下载安装:https://wkhtmltopdf.org/downloads.html
Windows安装直接下一步
到最后就可以。安装之后要配置环境变量,在path
中加入C:\Program Files\wkhtmltopdf\bin
,根据自己的安装目录。然后就可以在运行命令,打开cmd:
C:\Users\Administrator>wkhtmltopdf https://www.baidu.com C:\Users\Administrator\Desktop\demo.pdf
Loading pages (1/6)
Counting pages (2/6)
Resolving links (4/6)
Loading headers and footers (5/6)
Printing pages (6/6)
Done
此时桌面就会生成一个百度首页的PDF文件。
命令格式
wkhtmltopdf [GLOBAL OPTION]... [OBJECT]... <output file>
常用的参数选项
- –cookie 设置访问网页时的cookie,value 需要进行url编码(可重复使用此参数指定多个cookie)
- –javascript-delay 延迟一定的毫秒,等待javascript执行完成(默认值是200)
- –debug-javascript Show javascript debugging output(默认是不开启的)
更多参数选项参考官方文档
问题
有的web页面导出的PDF文件内容不全,可以延长JavaScript执行等待时间。但是有的web页面怎么延长都还是内容缺失,甚至生成空白页,目前没搞明白什么原因导致的。
最后给一段参考demo代码
package com.company.project.demo;
import javax.servlet.http.Cookie;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
public class WkhtmltopdfDemo implements Runnable {
private int consId = 1;
// wkhtmltopdf工作目录
public static final String WKHTMLTOPDF_WORKDIR = "C:\\Program Files\\wkhtmltopdf\\bin";
// wkhtmltopdf启动程序
public static final String WKHTMLTOPDF_PROGRAM = "C:\\Program Files\\wkhtmltopdf\\bin\\wkhtmltopdf.exe";
// 生成pdf存储路径
public static final String FILE_PATH = "C:\\Users\\Administrator\\Desktop\\test";
public boolean processTool(ArrayList<String> command) {
ProcessBuilder processBuilder = new ProcessBuilder(command);
processBuilder.directory(new File(WkhtmltopdfDemo.WKHTMLTOPDF_WORKDIR));
processBuilder.redirectErrorStream(true);
try {
Process process = processBuilder.start();
assert process.getInputStream().read() == -1;
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream(), StandardCharsets.UTF_8));
String line;
while ((line = bufferedReader.readLine()) != null) {
System.out.println("cmd" + line);
}
bufferedReader.close();
process.waitFor();
if (process.exitValue() != 0) {
System.out.println("非正常结束");
return false;
}
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
public static String createFileDirectory(String filePath) {
File file = new File(filePath);
File parentFile = file.getParentFile();
if (!parentFile.exists()) {
parentFile.mkdirs();
}
return filePath;
}
public boolean wkhtmltopdfTool(String htmlURL, String filePath, Cookie[] cookies) {
ArrayList<String> command = new ArrayList<>();
command.add(WkhtmltopdfDemo.WKHTMLTOPDF_PROGRAM);
for (Cookie cookie : cookies) {
String value = cookie.getValue();
command.add("--cookie");
command.add(cookie.getName());
command.add((value == null || "".equals(value.trim()) ? "null" : value));
}
// command.add("--javascript-delay");
// command.add("5000");
// command.add("--debug-javascript");
command.add(htmlURL);
command.add(filePath);
boolean result = new WkhtmltopdfDemo().processTool(command);
return result;
}
public boolean wkhtmltopdfTool(String htmlURL, String filePath) {
ArrayList<String> command = new ArrayList<>();
command.add(WkhtmltopdfDemo.WKHTMLTOPDF_PROGRAM);
// command.add("--javascript-delay");
// command.add("5000");
// command.add("--debug-javascript");
command.add(htmlURL);
command.add(filePath);
boolean result = new WkhtmltopdfDemo().processTool(command);
return result;
}
public byte[] htmltopdfByte(String htmlURL, String fileName) {
String filePath = WkhtmltopdfDemo.FILE_PATH + "\\" + fileName;
byte[] bytes = null;
WkhtmltopdfDemo wkhtmltopdfDemo = new WkhtmltopdfDemo();
boolean result = wkhtmltopdfDemo.wkhtmltopdfTool(htmlURL, WkhtmltopdfDemo.createFileDirectory(filePath));
if (result) {
File file = new File(filePath);
try {
FileInputStream inputStream = new FileInputStream(file);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
byte[] b = new byte[1024];
int n;
while ((n = inputStream.read(b)) != -1) {
outputStream.write(b, 0, n);
}
if (inputStream != null) {
inputStream.close();
}
if (outputStream != null) {
outputStream.close();
}
bytes = outputStream.toByteArray();
} catch (IOException e) {
e.printStackTrace();
} finally {
file.delete();
}
}
return bytes;
}
public File htmltopdfFile(String htmlURL, String fileName) {
String filePath = WkhtmltopdfDemo.FILE_PATH + "\\" + fileName;
File file = null;
boolean result = new WkhtmltopdfDemo().wkhtmltopdfTool(htmlURL, WkhtmltopdfDemo.createFileDirectory(filePath));
if (result) {
file = new File(filePath);
}
return file;
}
@Override
public void run() {
WkhtmltopdfDemo wkhtmltopdfDemo = new WkhtmltopdfDemo();
String htmlURL = "\"https://www.baidu.com\"";
while (consId > 0) {
String fileName = "test" + consId + ".pdf";
String filePath = WkhtmltopdfDemo.FILE_PATH + "\\" + fileName;
wkhtmltopdfDemo.wkhtmltopdfTool(htmlURL, WkhtmltopdfDemo.createFileDirectory(filePath));
consId--;
}
}
public static void main(String[] args) {
WkhtmltopdfDemo wkhtmltopdfDemo = new WkhtmltopdfDemo();
String htmlURL = "\"https://www.baidu.com\"";
String fileName = "test.pdf";
String filePath = WkhtmltopdfDemo.FILE_PATH + "\\" + fileName;
wkhtmltopdfDemo.wkhtmltopdfTool(htmlURL, WkhtmltopdfDemo.createFileDirectory(filePath));
}
}