【超全】网页转为图片的那些工具
这块的需求之前是没接触过的,还是一次在私下和朋友聊天中,他给我提的一个小需求,让我能在我的网站中的文章详情页里使用这个功能,将文章一键生成图片并下载,在找这方面的资料时也遇到了很多坑,其中坑的最狠的就是html2image这个功能(下边会详细说明),我的网站第一版的时候是使用的js脚本的方式生成图片,但是遇到的一个问题就是无法保存文章中的图片(我要这功能还有何用?),然后在各方查阅资料后,最终选用的cssbox这个功能(虽然现在还有一点点小问题,就是文章详情中的文字保存图片时,有些会乱码)。OK,话不多说,进入正题(以下工具的排序完全是按照使用简便性和效果的预期值,我感觉好用的是在最后介绍)。
共六种:
- cobra(lobobrowser)
- java原生代码(awt or swing)
- Robot
- html2image
- html2canvas.js
- cssbox
一、cobra(lobobrowser)
这个就算了,也别费力气找了。mvn库中已经下不下来这个的jar了, 网上也找不到,并且听说这个工具应该不支持css3
二、java原生代码(awt or swing)
/**
* 原理就是在现在的awt或者swing上显示网页然后将内容保存为一个图片
* @Description
* @author zhangyd
* @date 2017年3月13日 上午9:40:53
* @throws MalformedURLException
* @throws IOException
* @throws InterruptedException
*/
public static void awt() throws MalformedURLException, IOException, InterruptedException {
JEditorPane ed = new JEditorPane(new URL("http://www.imooc.com/article/16865"));
Thread.sleep(10000); // 标记
ed.setSize(1000, 1000);
// create a new image
BufferedImage image = new BufferedImage(ed.getWidth(), ed.getHeight(), BufferedImage.TYPE_INT_ARGB);
// paint the editor onto the image
SwingUtilities.paintComponent(image.createGraphics(), ed, new JPanel(), 0, 0, image.getWidth(), image.getHeight());
// save the image to file
ImageIO.write((RenderedImage) image, "png", new File("D:" + File.separator + "html.png"));
}
缺点:没办法控制延迟,即上方注释中的'标记'部分,必须手动进行控制延迟。因为如果不加延迟的话,是无法正常生成图片的。加延迟后生产的图片如下所示
简直了!
三、Robot:只能获取可视区域,纯属应急型功能
/**
* 方法详解:该方法利用Robot提供的强大桌面操作能力 硬性调用浏览器打开指定网页,并将网页信息保存到本地。
* 优势:简单易用,不需要任何第三方插件。
* 缺点:不能同时处理大量数据,技术含量过低,属于应急型技巧。
*
* @throws URISyntaxException
* @throws IOException
* @throws MalformedURLException
* @throws AWTException
*
*/
public static void robot() throws MalformedURLException, IOException, URISyntaxException, AWTException {
// 此方法仅适用于JdK1.6及以上版本
Desktop.getDesktop().browse(new URL("http://www.imooc.com/article/16865").toURI());
Robot robot = new Robot();
Dimension d = new Dimension(Toolkit.getDefaultToolkit().getScreenSize());
int width = (int) d.getWidth();
int height = (int) d.getHeight();
// 最大化浏览器
robot.keyRelease(KeyEvent.VK_F11);
robot.delay(2000); // 标记
Image image = robot.createScreenCapture(new Rectangle(0, 0, width, height));
BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics g = bi.createGraphics();
g.drawImage(image, 0, 0, width, height, null);
// 保存图片
ImageIO.write(bi, "jpg", new File("D:" + File.separator + "html.png"));
}
这个截图就是重新打开一个浏览器窗口,然后对当前屏幕可见区域进行截图。另外,这个工具使用时一定注意要加延迟(上方标记部分),因为如果不加延迟的话,还没等到浏览器打开,它就已经截图完成了,这时候截的应该就是你当前IDE的窗口了,并且这个延迟时间因机而异,有的电脑反应慢,10s打不开一个浏览器,这个时候的延迟时间就不好控制了。正常情况下截完图是这样的:
四、html2image:URL or HTML
这是我踩过的坑,坑了我不只一会半会!
这个工具需要第三方jar包(html2image-0.9.jar),同时支持url生成图片和html生成图片。
先贴两个关于这中方式用到的方法
private static void createFile(HtmlImageGenerator imageGenerator, String title) {
ImageOutputStream imOut = null;
FileOutputStream fileOut = null;
ByteArrayOutputStream byteOut = null;
try {
// 拿图片流
BufferedImage bufferedImage = imageGenerator.getBufferedImage();
bufferedImage.flush();
// 写图片流
byteOut = new ByteArrayOutputStream();
imOut = ImageIO.createImageOutputStream(byteOut);
ImageIO.write(bufferedImage, "png", imOut);
// 拿到图片流
byte[] b = byteOut.toByteArray();
String path = "D:" + File.separator + title + ".png";
fileOut = new FileOutputStream(path);
fileOut.write(b);
fileOut.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
close(imOut, fileOut, byteOut);
}
}
public static void close(Closeable... closeables) {
if (closeables != null && closeables.length > 0) {
for (Closeable closeable : closeables) {
if (closeable != null) {
try {
closeable.close();
} catch (IOException e) {
System.out.println("啊偶,年轻人搞事情啊...");
}
}
}
}
}
4.1 url2Image
public static void main(String[] args) throws Exception {
String url = "http://www.flyat.cc/article/295744a0af6942fbbf3e4dffa898bd48";
String title = "url2Image";
url2Image(url, title);
}
public static void url2Image(String url, String title) throws Exception {
HtmlImageGenerator imageGenerator = new HtmlImageGenerator();
// 设置图片的宽高,不是截屏内容的宽高
// Dimension ds = new Dimension(500, 4000);
// imageGenerator.setSize(ds);
imageGenerator.loadUrl(new URL(url));
createFile(imageGenerator, title);
}
生成的图片效果为:
文章内容还是可以的,就是样式方面有些不兼容,另外背景是蓝色是因为截出来的图片是透明背景的,因此会在图片查看器中显示深蓝色。一般如果选用这种方式生成图片的话,要考虑重新设计一个页面,以适应屏幕。比如我的站中重新设计的页面对应生成的图片为:
我是加了一个浅灰色的背景(html2image对样式支持的不是很好,因为是有特殊要求的,准备入坑)。
4.2 html2Image
顾名思义就是很久html代码生成图片,先看下html结构:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>html2image</title>
<style type="text/css">
body, html{max-width: 1366px;}
.article{position: relative;width: 100%;height: 100%;font-size: 12px;}
.article-body{border-bottom: 1px solid #e5e5e5}
/* 称呼 */
.article .salutation{font-weight: bold;font-size: 14px:}
.article .row{margin-left: 20px}
/* 底部 */
.article .footer{width: 100%;text-align: right;}
</style>
</head>
<body>
<div class="article">
<div class="article-body">
<p class="salutation">亲爱的${link.linkName}:</p>
<p class="row">您好!</p>
<p class="row">我可以对一个人无限的好,前提是值得! ————慕冬雪</p>
</div>
<div class="footer">
<p>网站管理员</p>
<p>${.now?string("yyyy年MM月dd日") }</p>
</div>
</div>
</body>
</html>
很正常的一段代码,那么在看下java相关代码
public static void main(String[] args) throws Exception {
String path = "D:\\links_mail.html";
File file = new File(path);
// 工具类,获取文件内容
String content = FileUtil.getFileContent(file);
System.out.println(content);
html2Image(content, "html2Image");
}
/**
* @author zhangyd
* @date 2017年3月6日 下午5:50:17
* @param content
* @throws Exception
*/
public static void html2Image(String content, String title) throws Exception {
HtmlImageGenerator imageGenerator = new HtmlImageGenerator();
// 设置图片的宽高,不是截屏内容的宽高
// Dimension ds = new Dimension(1000, 4000);
// imageGenerator.setSize(ds);
imageGenerator.loadHtml(content);
createFile(imageGenerator, title);
}
看下,生成的图片
是个空白的图片,为什么呢?html中明明有内容啊?
这就是我上面提到的那个坑爹的地方!
我把html改一下在看看结果哈
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<style type="text/css">
body, html{max-width: 1366px;}
.article{position: relative;width: 100%;height: 100%;font-size: 12px;}
.article-body{border-bottom: 1px solid #e5e5e5}
/* 称呼 */
.article .salutation{font-weight: bold;font-size: 14px:}
.article .row{margin-left: 20px}
/* 底部 */
.article .footer{width: 100%;text-align: right;}
</style>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>html2image</title>
</head>
<body>
<div class="article">
<div class="article-body">
<p class="salutation">亲爱的${link.linkName}:</p>
<p class="row">您好!</p>
<p class="row">我可以对一个人无限的好,前提是值得! ————慕冬雪</p>
</div>
<div class="footer">
<p>网站管理员</p>
<p>${.now?string("yyyy年MM月dd日") }</p>
</div>
</div>
</body>
</html>
生成图片
正常了!为什么正常?各位仔细对照一下html内容吧,给各位看下我当时的心情
所以这也是我不推荐这个工具的原因,正常的网站不一定全是自己的css样式,可能引入第三方样式比如bootstrap,这个时候就没法处理样式问题了。
五、html2canvas.js
这个是纯前端的工具,我测试的时候是发现无法支持文章内部图片的,可能有其他解决办法,各位可以自己去摸索下。
还是用上面那个html,不过我稍微改一下内容
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>html2image</title>
</head>
<body>
<div class="article">
<div class="article-body">
<p class="salutation">亲爱的${link.linkName}:</p>
<p class="row">您好!</p>
<p class="row">我可以对一个人无限的好,前提是值得! ————慕冬雪</p>
<p style="border: 1px red solid;height: 192px;"><img src="html2Image.png"></p>
</div>
</div>
<button id="generate">html2canvas生成图片</button>
<button id="download">下载图片</button>
<script src="http://cdn.bootcss.com/jquery/1.11.1/jquery.min.js"></script>
<script type="text/javascript" src="html2canvas.js"></script>
<script type="text/javascript" src="screenshot.js"></script>
</body>
</html>
加了个图片,并且图片外层加了一个边框,这样能更加清晰的看出来插件的问题
如果是纯文字的则可以用这种方式,毕竟不经过后端,只需要引用一个插件就可以,还是很方便的。
六、cssbox:目前我在用的,很棒
需要jar包依赖
<dependency>
<groupId>net.sf.cssbox</groupId>
<artifactId>cssbox</artifactId>
<version>4.12</version>
</dependency>
/**
* @Description cssbox插件生成图片
* @author zhangyd
* @date 2017年3月14日 上午11:50:20
*/
public static void cssbox() {
ImageRenderer render = new ImageRenderer();
render.setWindowSize(new Dimension(1400, 600), false);
String url = "http://www.flyat.cc/simpleArticle/295744a0af6942fbbf3e4dffa898bd48";
try {
render.renderURLByFile(url, new File("D:" + File.separator + "html.png"), ImageRenderer.Type.PNG);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
}
}
直接看效果吧
样式完美兼容!
完成!如果觉得我的文章能够帮助到你,请多多关注、多多分享,各位的支持就是我前进的动力。
源码及jar包- 本文标签: 其他
- 本文链接: https://zhyd.me/article/48
- 版权声明: 本文由张亚东原创发布,转载请遵循《署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)》许可协议授权