wkhtmltoimage開源工具的基本應用

讀大學時,微博興起,因爲140個字有限,因而有人開發了長微博,當時但想着開發一個長微博的應用。試用了幾款長微博工具,大部分都是隻能輸入文字和插件一兩張圖片,這種長微博工具實現不難。但若是想在長微博中支持富文本,例如插件表格之類的(http://www.changweibo.com/),那就沒那麼簡單了。 javascript

實現支持富文本的長微博,原理以下: html

1.客戶端提供一個富文本輸入框(CKeditor,Ueditor之類的) java

2.把在輸入框中輸入的html代碼發送到服務端,服務端解析html代碼,生成圖片返回客戶端 linux

重點要解決的問題是後臺如何解析html代碼並生成圖片。一個最初的想法是用htmlparse解析html代碼,對於簡單的html代碼這個方法可行,但若是html代碼的結構混亂就麻煩了。另外一個想法是在後臺用一個瀏覽器渲染這段html代碼,而後利用瀏覽器的功能把圖片導出。基於這個想法,用了javafx2.0裏面的Webview,Webview實質上就是一個瀏覽器,它用的是WebKit內核,用它能夠渲染html和執行javascript。用Webview生成圖片的代碼以下: web

import java.io.File;
import java.io.IOException;

import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.*;
import javafx.scene.image.Image;
import javafx.stage.Stage;
import javafx.scene.web.WebView;
import javafx.scene.web.WebEngine;
import javafx.concurrent.Worker.State;

import javax.imageio.ImageIO;

public class HtmlToImage extends Application {

	@Override
	public void start(Stage primaryStage) {
		final WebView view = new WebView();
		Scene scene = new Scene(view, 800, 600);
		primaryStage.setScene(scene);
		final WebEngine webEngine = view.getEngine();
		webEngine.load("http://www.huxiu.com/article/5840/1.html");
		primaryStage.show();
		//監聽webEngine加載進度,可能頁面加載不完整
		webEngine.getLoadWorker().stateProperty()
				.addListener(new ChangeListener<State>() {
					@Override
					public void changed(ObservableValue<? extends State> ov,
							State oldState, State newState) {
						if (newState == State.SUCCEEDED) {
							snapshot(view);
						}
					}
				});

	}

	public void snapshot(Node view) {
		Image image = view.snapshot(null, null);
		try {
			ImageIO.write(SwingFXUtils.fromFXImage(image, null), "png",
					new File("D:\\" + System.currentTimeMillis()
							+ ".png"));
			System.out.println("圖片已生成");
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		launch(args);
	}
}

生成的圖片以下: windows



圖1 api

這個方法能夠把html代碼渲染成圖片而且導出,但只是一個簡單的截屏功能,若是屏幕上出現滾動條,則只能導出屏幕上顯示的那部分效果,因此這個方案也是不可行的。但它給咱們提供了一個很好的思路。即經過瀏覽器來渲染html,利用瀏覽器提供的api導出圖片。Chrome和Firfox這兩大瀏覽器的內核都是開源的,能夠從這些開源的瀏覽器內核入手。看它們有沒有提供對應的API。在谷歌上搜索了一番,找到了一個可用的開源目wkhtmltopdf,這個開源項目能夠把html轉換成pdf或者image,它也是基於webkit內核實現這些功能的。wkhtmltopdf提供了windows、linux、和Mac 三個版本,下面以windows版本爲例,說明它的用法。 瀏覽器

1.先下載libwkhtmltox-0.11.0_rc1.zip,解壓安裝 app

2.在命令行下輸入:wkhtmltopdf www.google.com.hk myhomepage.pdf 就能夠把谷歌的首頁導出爲pdf文件, ide

   同理,wkhtmltoimage www.google.com.hk myhomepage.jpg 能夠把谷歌的首頁導出爲圖片。

注意:wkhtmltopdf和wkhtmltoimage對中文編碼支持不友好,若是網頁是GBK編碼,生成的圖片或者pdf是亂碼,因此最好先把網頁下載到本地,改爲UTF-8編碼,再調用這兩個工具生成圖片或者pdf。

以上只是簡單應用wkhtmltopdf的命令,事實上這兩個命令能夠帶參數的,詳細的參數說明能夠看官方文檔。

3.在java程序中調用wkhtmltoimage。由於wkhtmltoimage並無提供java api,因此只能經過java程序啓動命令行,經過命令行調用wkhtmltoimage來完成任務。

public class HtmlToImage{
	public static void main(String[] args){
		ProcessBuilder pb = new ProcessBuilder("D:\\Program Files\\wkhtmltopdf\\wkhtmltoimage", "www.baidu.com", "D:\\test.jpg");
		Process process;
		try {
			process = pb.start();
			//注意,調用process.getErrorStream()而不是process.getInputStream()
			BufferedReader errStreamReader = new BufferedReader(new InputStreamReader(process.getErrorStream())); 
			System.out.println("read errstreamreader");
			String line = null;
			line = errStreamReader.readLine(); 
			while(line != null) { 
			    System.out.println(line); 
			    line = errStreamReader.readLine(); 
			}
			process.destroy();
		    System.out.println("destroyed process");
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}

總結:wkhtmltopdf和wkhtmltoimage是一個功能強大的開源工具,能夠實現不少相似的功能。例如,用谷歌搜索時,把鼠標移動到連接上面,會顯示該網頁的縮略圖,這個功能能夠用wkhtmltoimage來實現。若是想把博客導出爲pdf,能夠用wkhtmltopdf來實現。

相關文章
相關標籤/搜索