原创

【超全】网页转为图片的那些工具

这块的需求之前是没接触过的,还是一次在私下和朋友聊天中,他给我提的一个小需求,让我能在我的网站中的文章详情页里使用这个功能,将文章一键生成图片并下载,在找这方面的资料时也遇到了很多坑,其中坑的最狠的就是html2image这个功能(下边会详细说明),我的网站第一版的时候是使用的js脚本的方式生成图片,但是遇到的一个问题就是无法保存文章中的图片(我要这功能还有何用?),然后在各方查阅资料后,最终选用的cssbox这个功能(虽然现在还有一点点小问题,就是文章详情中的文字保存图片时,有些会乱码)。OK,话不多说,进入正题(以下工具的排序完全是按照使用简便性和效果的预期值,我感觉好用的是在最后介绍)。

共六种:

  1. cobra(lobobrowser)
  2. java原生代码(awt or swing)
  3. Robot
  4. html2image
  5. html2canvas.js
  6. 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"));
 }

缺点:没办法控制延迟,即上方注释中的'标记'部分,必须手动进行控制延迟。因为如果不加延迟的话,是无法正常生成图片的。加延迟后生产的图片如下所示

关于java把网页报存为图片的那些工具文章的图片

简直了!

三、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打不开一个浏览器,这个时候的延迟时间就不好控制了。正常情况下截完图是这样的:

关于java把网页报存为图片的那些工具文章的图片

四、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);
}

生成的图片效果为:

关于java把网页报存为图片的那些工具文章的图片

文章内容还是可以的,就是样式方面有些不兼容,另外背景是蓝色是因为截出来的图片是透明背景的,因此会在图片查看器中显示深蓝色。一般如果选用这种方式生成图片的话,要考虑重新设计一个页面,以适应屏幕。比如我的站中重新设计的页面对应生成的图片为:

关于java把网页报存为图片的那些工具文章的图片

我是加了一个浅灰色的背景(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);
}

看下,生成的图片

关于java把网页报存为图片的那些工具文章的图片

是个空白的图片,为什么呢?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>

生成图片

关于java把网页报存为图片的那些工具文章的图片

正常了!为什么正常?各位仔细对照一下html内容吧,给各位看下我当时的心情

关于java把网页报存为图片的那些工具文章的图片

所以这也是我不推荐这个工具的原因,正常的网站不一定全是自己的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>

加了个图片,并且图片外层加了一个边框,这样能更加清晰的看出来插件的问题

关于java把网页报存为图片的那些工具文章的图片

如果是纯文字的则可以用这种方式,毕竟不经过后端,只需要引用一个插件就可以,还是很方便的。

六、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();
	}
}

直接看效果吧

关于java把网页报存为图片的那些工具文章的图片

样式完美兼容!

完成!如果觉得我的文章能够帮助到你,请多多关注、多多分享,各位的支持就是我前进的动力。

源码及jar包


正文到此结束