java实现将html网页转pdf,如果需求只是将一些简单的html元素转成pdf,那么使用 itext 或者 FlyingSaucer 就可以搞定,但是真正的网页url类型的html涉及到的 html 语法和 css语法实在是太复杂,itext 和 FlyingSaucer 根本没法搞定。
最后发现使用 phantomjs 可以完美将html转换为pdf,大概思路如下:
一、下载phantomjs
https://phantomjs.org/download.html 根据操作系统下载对应的phantomjs版本
二、编写 html2pdf.js
内容如下:
var page = require('webpage').create();
var system = require('system');
// 读取命令行参数,也就是js文件路径。
if (system.args.length === 1) {
console.log('Usage: phantomjs html2pdf.js ');
//这行代码很重要。凡是结束必须调用。否则phantomjs不会停止
phantom.exit();
}
page.settings.loadImages = true; //加载图片
page.settings.resourceTimeout = 30000;//超过30秒放弃加载
var address = system.args[1];
// server in windows: width + 'mm', linux: (width * 3.7794).toFixed(1) + 'px'
// 下面是从命令行中获取 pdf的高度、宽度 和 pdf文件的路径
var width2 = system.args[2];
var height2 = system.args[3];
var pdfPath = system.args[4];
console.log(width2);
console.log(height2);
// 如果对pdf尺寸没有特殊要求也可以将宽度和高度写死
page.paperSize = { width: width2,height:height2};
page.open(address, function (status) {
if (status !== 'success') {
console.log('Unable to load the address!');
phantom.exit(1);
} else {
window.setTimeout(function () {
console.log("begin...");
page.render(pdfPath);
console.log(pdfPath);
phantom.exit(); // 一定要调用这个方法
console.log("end...");
}, 1000);
}
});
三、执行命令行语句验证pdf生成的效果
/test/phantomjs /test/html2pdf.js http://www.baidu.com 1000px 1000px /test/a.pdf
执行这条命令,检查生成pdf是否符合要求。如果不行则尝试调整参数或者脚本
四、java中调用命令
public static void html2Pdf(String phantomjs, String url, String html2pdfjs
, Integer width, Integer height, String pdfPath) {
InputStream is = null;
try {
System.out.println(url);
File pdfFile = new File(pdfPath);
File parentFile = pdfFile.getParentFile();
if(!parentFile.exists()) {
parentFile.mkdirs();
}
String os = System.getProperty("os.name").toLowerCase();
String w = null, h = null;
if(os.contains("linux")) {
w = String.format("%.2f", width * 3.7794) + "px";
h = String.format("%.2f", height * 3.7794) + "px";
} else {
w = width + "mm";
h = height + "mm";
}
System.out.println(os + "===" + w + "=======" + h);
//执行phantomjs 生成js
Runtime rt = Runtime.getRuntime();
String cmd = phantomjs + " " + html2pdfjs + " " + url + " " + w + " " + h + " " + pdfPath;
System.out.println("cmd===" + cmd);
Process p = rt.exec(cmd);
is = p.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
StringBuffer sbf = new StringBuffer();
String tmp = "";
while ((tmp = br.readLine()) != null) {
sbf.append(tmp);
}
String resultstr = sbf.toString();
System.out.println(resultstr);
p.waitFor(); // 等待运行结束
} catch (Exception e) {
e.printStackTrace();
} finally {
if(is != null) {
try {
is.close();
} catch (Exception e) {
}
}
}
return null;
}
width 和 height 两个参数在windos环境和在linux环境下传给phantomjs达到的效果竟然不一样,所以上面的程序专门做了不同的处理。
五、踩过的坑
1、linux下java调用命令及参数中如果带了 & 符号,会导致命令执行失败,同时又找不到原因。因为 & 符号在linux命令下有特殊的含义,因此 网页的url中如果带了&符号(比如url中的&是传递参数的)则pdf会生成不正确
2、如果尝试将带&的网页url 用引号包起来,在linux命令行下可以顺利执行,但是java的Runtime.exec()去执行命令还是不能正确生成pdf文件,好像是因为Runtime.exec()对参数中的引号进行特殊的处理。
因此,如果能自己控制网页url,则需要将网页url中的&替换掉,改成其他方式传参。如果是别人的网页url,在linux似乎没有好的办法解决。
六、参考资料
phantomjs 参考资料如下:
https://phantomjs.org/download.html
https://www.npmjs.com/package/phantom-html2pdf
https://phantomjs.org/api/webpage/property/paper-size.html
本文内容到此结束。