Java利用Phantomjs實(shí)現(xiàn)生成圖片的功能
今天,給大家分享一個(gè)Java后端利用Phantomjs實(shí)現(xiàn)生成圖片的功能,同學(xué)們使用的時(shí)候,可以參考下!
PhantomJS簡(jiǎn)介
首先,什么是PhantomJS?
根據(jù)官網(wǎng)介紹:
PhantomJS is a command-line tool. -- 其實(shí)就是一個(gè)命令行工具。
PhantomJS的下載地址:
Windows:phantomjs-2.1.1-windows.zip
Linux:phantomjs-2.1.1-linux-x86_64.tar.bz2;phantomjs-2.1.1-linux-i686.tar.bz2
MacOS:phantomjs-2.1.1-macosx.zip
下載下來(lái)后,我們看到bin目錄下就是可執(zhí)行文件phantomjs.exe,我們可以將它配置到環(huán)境變量中,方便命令使用!
還有一個(gè)examples目錄,它下面是很多js樣例,關(guān)于這些樣例作用,參考官網(wǎng)解釋?zhuān)o大家做個(gè)簡(jiǎn)單翻譯:
1. Basic examples
arguments.js:顯示傳遞給腳本的參數(shù) countdown.js:打印10秒倒計(jì)時(shí) echoToFile.js:將命令行參數(shù)寫(xiě)入文件 fibo.js:列出了斐波那契數(shù)列中的前幾個(gè)數(shù)字 hello.js:顯示著名消息 module.js:并universe.js演示模塊系統(tǒng)的使用 outputEncoding.js:顯示各種編碼的字符串 printenv.js:顯示系統(tǒng)的環(huán)境變量 scandir.js:列出目錄及其子目錄中的所有文件 sleepsort.js:對(duì)整數(shù)進(jìn)行排序并根據(jù)其值延遲顯示 version.js:打印出PhantomJS版本號(hào) page_events.js:打印出頁(yè)面事件觸發(fā):有助于更好地掌握page.on*回調(diào)2. Rendering/rasterization
colorwheel.js:使用HTML5畫(huà)布創(chuàng)建色輪 rasterize.js:將網(wǎng)頁(yè)光柵化為圖像或PDF render_multi_url.js:將多個(gè)網(wǎng)頁(yè)渲染為圖像3. Page automation
injectme.js:將自身注入到網(wǎng)頁(yè)上下文中 phantomwebintro.js:使用jQuery從phantomjs.org讀取.version元素文本 unrandomize.js:在頁(yè)面初始化時(shí)修改全局對(duì)象 waitfor.js:等待直到測(cè)試條件為真或發(fā)生超時(shí)4. Network
detectniff.js:檢測(cè)網(wǎng)頁(yè)是否嗅探用戶(hù)代理 loadspeed.js:計(jì)算網(wǎng)站的加載速度 netlog.js:轉(zhuǎn)儲(chǔ)所有網(wǎng)絡(luò)請(qǐng)求和響應(yīng) netsniff.js:以HAR格式捕獲網(wǎng)絡(luò)流量 post.js:將HTTP POST請(qǐng)求發(fā)送到測(cè)試服務(wù)器 postserver.js:?jiǎn)?dòng)Web服務(wù)器并向其發(fā)送HTTP POST請(qǐng)求 server.js:?jiǎn)?dòng)Web服務(wù)器并向其發(fā)送HTTP GET請(qǐng)求 serverkeepalive.js:?jiǎn)?dòng)Web服務(wù)器,以純文本格式回答 simpleserver.js:?jiǎn)?dòng)Web服務(wù)器,以HTML格式回答5. Testing
run-jasmine.js:運(yùn)行基于Jasmine的測(cè)試 run-qunit.js:運(yùn)行基于QUnit的測(cè)試6. Browser
features.js:檢測(cè)瀏覽器功能使用modernizr.js useragent.js:更改瀏覽器的用戶(hù)代理屬性今天,我們根據(jù)網(wǎng)頁(yè)URL生成圖片,使用的就是rasterize.js:將網(wǎng)頁(yè)光柵化為圖像或PDF。
了解rasterize.js
我們來(lái)看一下rasterize.js的內(nèi)容(源文件對(duì)size的處理有錯(cuò)誤,這里已修正?。?/p>
'use strict';var page = require(’webpage’).create(), system = require(’system’), address, output, size;if (system.args.length < 3 || system.args.length > 5) { console.log(’Usage: rasterize.js URL filename [paperwidth*paperheight|paperformat] [zoom]’); console.log(’ paper (pdf output) examples: '5in*7.5in', '10cm*20cm', 'A4', 'Letter'’); console.log(’ image (png/jpg output) examples: '1920px' entire page, window width 1920px’); console.log(’ '800px*600px' window, clipped to 800x600’); phantom.exit(1);} else { address = system.args[1]; output = system.args[2]; page.viewportSize = { width: 800, height: 200 }; if (system.args.length > 3 && system.args[2].substr(-4) === '.pdf') { size = system.args[3].split(’*’); page.paperSize = size.length === 2 ? { width: size[0], height: size[1], margin: ’0px’ } : { format: system.args[3], orientation: ’portrait’, margin: ’1cm’ }; } else if (system.args.length > 3 && system.args[3].substr(-2) === 'px') { size = system.args[3].split(’*’); if (size.length === 2) { var pageWidth = parseInt(size[0].substr(0,size[0].indexOf('px')), 10); var pageHeight = parseInt(size[1].substr(0,size[1].indexOf('px')), 10); page.viewportSize = { width: pageWidth, height: pageHeight }; page.clipRect = { top: 0, left: 0, width: pageWidth, height: pageHeight }; } else { var pageWidth = parseInt(system.args[3].substr(0,system.args[3].indexOf('px')), 10); var pageHeight = parseInt(pageWidth * 3/4, 10); // it’s as good an assumption as any page.viewportSize = { width: pageWidth, height: pageHeight }; } } if (system.args.length > 4) { page.zoomFactor = system.args[4]; } page.open(address, function (status) { if (status !== ’success’) { console.log(’Unable to load the address!’); phantom.exit(1); } else { window.setTimeout(function () {page.render(output);phantom.exit(); }, 200); } });}
有過(guò)終端開(kāi)發(fā)的人,對(duì)這段命令理解起來(lái)都不會(huì)太難,這里我就不多說(shuō)了,后面,我們重點(diǎn)介紹它的使用!
使用方法
首先,我們將Phantom的包引入工程,放在resources目錄下。因?yàn)槲覀円WC本地windows開(kāi)發(fā)與服務(wù)器linux環(huán)境開(kāi)發(fā)打包后都能運(yùn)行,所以,我們將windows和linux兩個(gè)包都引入。
然后,我們創(chuàng)建Phantom的使用工具類(lèi)PhantomTools.class:
package test;import lombok.extern.slf4j.Slf4j;import org.apache.commons.io.FileUtils;import org.apache.commons.io.IOUtils;import org.apache.commons.lang3.StringUtils;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.util.UUID;/** * 網(wǎng)頁(yè)轉(zhuǎn)圖片處理類(lèi),使用外部CMD * * @author lekkoli */@Slf4jpublic class PhantomTools { /** * 可執(zhí)行文件phantomjs.exe路徑 */ private final String phantomjsPath; /** * 快照?qǐng)D生成JS路徑 */ private final String rasterizePath; /** * 臨時(shí)圖片前綴 */ private static final String FILE_PREFIX = 'TIG-AE-'; /** * 臨時(shí)圖片后綴 */ private static final String FILE_SUFFIX = '.jpg'; /** * 構(gòu)造參數(shù) * 獲取phantomjs路徑 */ public PhantomTools() { String bootPath = new File(this.getClass().getResource('/').getPath()).getPath(); phantomjsPath = String.join(File.separator, bootPath, 'phantomjs-2.1.1-windows', 'bin', 'phantomjs'); rasterizePath = String.join(File.separator, bootPath, 'phantomjs-2.1.1-windows', 'examples', 'rasterize.js'); } /** * url 中需要轉(zhuǎn)義的字符 * 1. + URL 中+號(hào)表示空格 %2B * 2. 空格 URL中的空格可以用+號(hào)或者編碼 %20 * 3. / 分隔目錄和子目錄 %2F * 4. ? 分隔實(shí)際的 URL 和參數(shù) %3F * 5. % 指定特殊字符 %25 * 6. # 表示書(shū)簽 %23 * 7. & URL 中指定的參數(shù)間的分隔符 %26 * 8. = URL 中指定參數(shù)的值 %3D * * @param url 需要轉(zhuǎn)義的URL * @return 轉(zhuǎn)義后的URL */ public String parseUrl(String url) { String parsedUrl = StringUtils.replace(url, '&', '%26'); log.info('[解析后的URL:{}]', parsedUrl); return parsedUrl; } /** * 根據(jù)URL生成指定fileName的字節(jié)數(shù)組 * * @param url 請(qǐng)求URL * @return 圖片字節(jié)數(shù)組 */ public byte[] create(String url) { return create(url, null); } /** * 根據(jù)URL生成指定fileName的字節(jié)數(shù)組 * * @param url 請(qǐng)求URL * @param size 指定圖片尺寸,例如:1000px*800px * @return 圖片字節(jié)數(shù)組 */ public byte[] create(String url, String size) { // 服務(wù)器文件存放地址 String filePath = FileUtils.getTempDirectoryPath() + FILE_PREFIX + UUID.randomUUID().toString() + FILE_SUFFIX; try { // 執(zhí)行快照命令 String command = String.join(StringUtils.SPACE, phantomjsPath, rasterizePath, url, filePath, size); log.info('[執(zhí)行命令:{}]', command); // 執(zhí)行命令操作 Process process = Runtime.getRuntime().exec(command); // 一直掛起,直到子進(jìn)程執(zhí)行結(jié)束,返回值0表示正常退出 if (process.waitFor() != 0) {log.error('[執(zhí)行本地Command命令失敗] [Command:{}]', command);return new byte[0]; } // 判斷生成的圖片是否存在 File file = FileUtils.getFile(filePath); if (!file.exists()) {log.error('[本地文件'{}'不存在]', file.getName());return new byte[0]; } // 將快照?qǐng)D片生成字節(jié)數(shù)組 byte[] bytes = IOUtils.toByteArray(new FileInputStream(file)); log.info('[圖片生成結(jié)束] [圖片大?。簕}KB]', bytes.length / 1024); return bytes; } catch (IOException | InterruptedException e) { log.error('[圖片生成失敗]', e); } finally { FileUtils.deleteQuietly(FileUtils.getFile(filePath)); } return new byte[0]; }}
上面工具類(lèi),通過(guò)構(gòu)造方法初始化了命令包路徑,調(diào)用parseUrl()方法對(duì)URL中含有的&符號(hào)做了替換,最核心的命令執(zhí)行,采用Process對(duì)象完成,最后輸出到臨時(shí)目錄下的圖片文件。這就是phantomjs對(duì)Web訪問(wèn)頁(yè)的圖片生成流程。
其中,Process對(duì)象底層調(diào)用的其實(shí)就是ProcessBuilder。
public Process exec(String[] cmdarray, String[] envp, File dir) throws IOException { return new ProcessBuilder(cmdarray) .environment(envp) .directory(dir) .start();}
ProcessBuilder會(huì)調(diào)用ProcessImpl的許多底層native方法完成URL訪問(wèn)與圖片生成。
測(cè)試方法:
public static void main(String[] arg) throws IOException { String url = 'https://www.cnblogs.com/ason-wxs/'; PhantomTools phantomTools = new PhantomTools(); String parsedUrl = phantomTools.parseUrl(url); byte[] byteImg = phantomTools.create(parsedUrl); File descFile = new File(FileUtils.getTempDirectoryPath() + 'test.png'); FileUtils.touch(descFile); FileUtils.writeByteArrayToFile(descFile, byteImg);}
測(cè)試結(jié)果我就不貼出來(lái)了,無(wú)非將我的博客首頁(yè)生成圖片保存到指定文件test.png中。
好了,希望上面對(duì)PhantomJS的介紹對(duì)你今后工作有所幫助!
以上就是Java利用Phantomjs實(shí)現(xiàn)生成圖片的功能的詳細(xì)內(nèi)容,更多關(guān)于JAVA 生成圖片的資料請(qǐng)關(guān)注好吧啦網(wǎng)其它相關(guān)文章!
相關(guān)文章:
1. XML解析錯(cuò)誤:未組織好 的解決辦法2. JSP的Cookie在登錄中的使用3. 博客日志摘要暨RSS技術(shù)4. 告別AJAX實(shí)現(xiàn)無(wú)刷新提交表單5. SSM框架整合JSP中集成easyui前端ui項(xiàng)目開(kāi)發(fā)示例詳解6. 使用XSL將XML文檔中的CDATA注釋輸出為HTML文本7. ASP.NET Core實(shí)現(xiàn)中間件的幾種方式8. JSP之表單提交get和post的區(qū)別詳解及實(shí)例9. XMLDOM對(duì)象方法:對(duì)象屬性10. ASP常用日期格式化函數(shù) FormatDate()
