讀大學時,微博興起,因爲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來實現。