html转图片或pdf方案
前言
java将html转图片等方案,仅适合很简单的页面,对CSS的支持有限,效果不理想。
如:
<dependency>
<groupId>com.github.xuwei-k</groupId>
<artifactId>html2image</artifactId>
<version>0.1.0</version>
</dependency>
<dependency>
<groupId>org.xhtmlrenderer</groupId>
<artifactId>flying-saucer-core</artifactId>
<version>9.1.16</version>
</dependency>
<dependency>
<groupId>net.sf.cssbox</groupId>
<artifactId>cssbox</artifactId>
<version>5.0.0</version>
</dependency>
成熟方案一
https://blog.csdn.net/weixin_41118077/article/details/119934868
java方案,效果也还可以,样式支持较全
<dependency>
<groupId>com.openhtmltopdf</groupId>
<artifactId>openhtmltopdf-core</artifactId>
<version>1.0.9</version>
</dependency>
<dependency>
<groupId>com.openhtmltopdf</groupId>
<artifactId>openhtmltopdf-java2d</artifactId>
<version>1.0.9</version>
</dependency>
成熟方案二
wkhtmltopdf和wkhtmltoimage是开源(LGPLv3)命令行工具,使用Qt WebKit渲染引擎将HTML渲染为PDF和各种图像格式。它们完全“无头”运行,并且不需要显示器或显示服务。
开发语言:C++
https://wkhtmltopdf.org/
成熟方案三
Doctron,它是基于Docker、无状态、简单、快速、高质量的文档转换服务。目前支持将html转为pdf、图片(使用chrome(Chromium)浏览器内核,保证转换质量)。支持PDF添加水印。
开发语言:go
开源项目地址:https://github.com/lampnick/doctron
对比
渲染内核不同:Chromium > Qt WebKit(不支持ES6) (样式特性支持程度)
速度对比:C++ > go
图片质量:wkhtmltoX > Doctron
- | png | jpg_100 | jpg_50 |
---|---|---|---|
wkhtml | 24.7M | 1.8M | 338K |
doctron | 2.2M | 1.7M | 302K |
部署便利: Doctron > wkhtmltoX
- png比jpeg清晰度更高
- wkhtml的png确实非常清楚,但是体积太大,慎重考虑
补充可选方案
补充一:rayin
https://gitee.com/Rayin/rayin
补充二:cutycapt
https://www.cnblogs.com/tdalcn/p/8466122.html
https://www.likecs.com/show-733340.html
由于Doctron截较长页面时超时(docker部署可复现,已提github issue,但本地启动项目没这个问题,可能是环境原因折腾两天未果决定换方案),wkhtmltoX样式支持不太好个别样式错乱了(还有一个原因是产出的结果图有白边,可能是bug),最终选择了cutycapt方案。
转长图服务的备选方案
1.服务:nginx/openresty代理某个目录,生成的图片放里面,请求来了就调用下命令生成图片,响应回去url,谁调用,谁自己处理文件,决定是一次性的还是上传oss。
2.安全:只允许生产和测试服务器ip访问,防火墙或lua处理
3.垃圾处理:系统的定时任务
https://www.cnblogs.com/xiao-xue-di/p/14689388.html
nginx性能好,无需java环境,节省服务器资源,不用写代码
lua获取get请求参数
https://blog.csdn.net/xiejunna/article/details/75098266
lua获取post请求参数
https://www.cnblogs.com/cherylgi/p/16428883.html
lua调用命令行生成图片
https://blog.csdn.net/Outbreak_Jinx/article/details/90722210
前端方式
<script src="https://cdn.bootcdn.net/ajax/libs/html2canvas/1.4.1/html2canvas.min.js"></script>
<script src="https://cdn.bootcdn.net/ajax/libs/downloadjs/1.4.8/download.min.js"></script>
<script>
// 使用html2canvas 转换html为canvas
function downloadForJS() {
html2canvas(document.querySelector(".container"), {
scale: 2
}).then(function (canvas) {
var imgUri = canvas.toDataURL().replace("image/png", "image/octet-stream"); // 获取生成的图片的url
var box = document.querySelector(".container");
download(imgUri, 'my-node666.jpg');
})
}
</script>
当心跨域问题,让图片链接不跨域或者将url替换为base64
@Test
public void url2base64() {
String html = FileUtil.readUtf8String("D:\\example\\refactor\\test.html");
Pattern pattern = Pattern.compile("https?://.*\\.(png|jpe?g)", Pattern.MULTILINE);
List<String> all = ReUtil.findAll(pattern, html, 0);
Set<String> distinct = new HashSet<>(all);
Map<String, String> map = distinct.parallelStream().collect(Collectors.toMap(s -> s, s -> imgToBase64Short(s)));
for (Map.Entry<String, String> entry : map.entrySet()) {
html = StrUtil.replace(html, entry.getKey(), entry.getValue());
}
FileUtil.writeUtf8String(html, "testB64.html");
}
public static String imgToBase64Short(String path) {
try {
return ImgUtil.toBase64DataUri(ImgUtil.getImage(new URL(path)),"png");
} catch (MalformedURLException e) {
e.printStackTrace();
return path;
}
}