今天,给大家分享一个Java后端利用Phantomjs实现生成图片的功能,同学们使用的时候,可以参考下!

PhantomJS简介

首先,什么是PhantomJS?

根据官网介绍:

PhantomJS is a command-line tool. -- 其实就是一个命令行工具。

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

下载下来后,我们看到bin目录下就是可执行文件phantomjs.exe,我们可以将它配置到环境变量中,方便命令使用!

还有一个examples目录,它下面是很多js样例,关于这些样例作用,参考官网解释,给大家做个简单翻译:

1. Basic examples

arguments.js:显示传递给脚本的参数

countdown.js:打印10秒倒计时

echoToFile.js:将命令行参数写入文件

fibo.js:列出了斐波那契数列中的前几个数字

hello.js:显示著名消息

module.js:并universe.js演示模块系统的使用

outputEncoding.js:显示各种编码的字符串

printenv.js:显示系统的环境变量

scandir.js:列出目录及其子目录中的所有文件

sleepsort.js:对整数进行排序并根据其值延迟显示

version.js:打印出PhantomJS版本号

page_events.js:打印出页面事件触发:有助于更好地掌握page.on*回调

2. Rendering/rasterization

colorwheel.js:使用HTML5画布创建色轮

rasterize.js:将网页光栅化为图像或PDF

render_multi_url.js:将多个网页渲染为图像

3. Page automation

injectme.js:将自身注入到网页上下文中

phantomwebintro.js:使用jQuery从phantomjs.org读取.version元素文本

unrandomize.js:在页面初始化时修改全局对象

waitfor.js:等待直到测试条件为真或发生超时

4. Network

detectniff.js:检测网页是否嗅探用户代理

loadspeed.js:计算网站的加载速度

netlog.js:转储所有网络请求和响应

netsniff.js:以HAR格式捕获网络流量

post.js:将HTTP POST请求发送到测试服务器

postserver.js:启动Web服务器并向其发送HTTP POST请求

server.js:启动Web服务器并向其发送HTTP GET请求

serverkeepalive.js:启动Web服务器,以纯文本格式回答

simpleserver.js:启动Web服务器,以HTML格式回答

5. Testing

run-jasmine.js:运行基于Jasmine的测试

run-qunit.js:运行基于QUnit的测试

6. Browser

features.js:检测浏览器功能使用modernizr.js

useragent.js:更改浏览器的用户代理属性

今天,我们根据网页URL生成图片,使用的就是rasterize.js:将网页光栅化为图像或PDF。

了解rasterize.js

我们来看一下rasterize.js的内容(源文件对size的处理有错误,这里已修正!):

"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);

}

});

}

有过终端开发的人,对这段命令理解起来都不会太难,这里我就不多说了,后面,我们重点介绍它的使用!

使用方法

首先,我们将Phantom的包引入工程,放在resources目录下。因为我们要保证本地windows开发与服务器linux环境开发打包后都能运行,所以,我们将windows和linux两个包都引入。

然后,我们创建Phantom的使用工具类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;

/**

* 网页转图片处理类,使用外部CMD

*

* @author lekkoli

*/

@Slf4j

public class PhantomTools {

/**

* 可执行文件phantomjs.exe路径

*/

private final String phantomjsPath;

/**

* 快照图生成JS路径

*/

private final String rasterizePath;

/**

* 临时图片前缀

*/

private static final String FILE_PREFIX = "TIG-AE-";

/**

* 临时图片后缀

*/

private static final String FILE_SUFFIX = ".jpg";

/**

* 构造参数

* 获取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 中需要转义的字符

* 1. + URL 中+号表示空格 %2B

* 2. 空格 URL中的空格可以用+号或者编码 %20

* 3. / 分隔目录和子目录 %2F

* 4. ? 分隔实际的 URL 和参数 %3F

* 5. % 指定特殊字符 %25

* 6. # 表示书签 %23

* 7. & URL 中指定的参数间的分隔符 %26

* 8. = URL 中指定参数的值 %3D

*

* @param url 需要转义的URL

* @return 转义后的URL

*/

public String parseUrl(String url) {

String parsedUrl = StringUtils.replace(url, "&", "%26");

log.info("[解析后的URL:{}]", parsedUrl);

return parsedUrl;

}

/**

* 根据URL生成指定fileName的字节数组

*

* @param url 请求URL

* @return 图片字节数组

*/

public byte[] create(String url) {

return create(url, null);

}

/**

* 根据URL生成指定fileName的字节数组

*

* @param url 请求URL

* @param size 指定图片尺寸,例如:1000px*800px

* @return 图片字节数组

*/

public byte[] create(String url, String size) {

// 服务器文件存放地址

String filePath = FileUtils.getTempDirectoryPath() + FILE_PREFIX + UUID.randomUUID().toString() + FILE_SUFFIX;

try {

// 执行快照命令

String command = String.join(StringUtils.SPACE, phantomjsPath, rasterizePath, url, filePath, size);

log.info("[执行命令:{}]", command);

// 执行命令操作

Process process = Runtime.getRuntime().exec(command);

// 一直挂起,直到子进程执行结束,返回值0表示正常退出

if (process.waitFor() != 0) {

log.error("[执行本地Command命令失败] [Command:{}]", command);

return new byte[0];

}

// 判断生成的图片是否存在

File file = FileUtils.getFile(filePath);

if (!file.exists()) {

log.error("[本地文件\"{}\"不存在]", file.getName());

return new byte[0];

}

// 将快照图片生成字节数组

byte[] bytes = IOUtils.toByteArray(new FileInputStream(file));

log.info("[图片生成结束] [图片大小:{}KB]", bytes.length / 1024);

return bytes;

} catch (IOException | InterruptedException e) {

log.error("[图片生成失败]", e);

} finally {

FileUtils.deleteQuietly(FileUtils.getFile(filePath));

}

return new byte[0];

}

}

上面工具类,通过构造方法初始化了命令包路径,调用parseUrl()方法对URL中含有的&符号做了替换,最核心的命令执行,采用Process对象完成,最后输出到临时目录下的图片文件。这就是phantomjs对Web访问页的图片生成流程。

其中,Process对象底层调用的其实就是ProcessBuilder。

public Process exec(String[] cmdarray, String[] envp, File dir)

throws IOException {

return new ProcessBuilder(cmdarray)

.environment(envp)

.directory(dir)

.start();

}

ProcessBuilder会调用ProcessImpl的许多底层native方法完成URL访问与图片生成。

测试方法:

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);

}

测试结果我就不贴出来了,无非将我的博客首页生成图片保存到指定文件test.png中。

好了,希望上面对PhantomJS的介绍对你今后工作有所帮助!

以上就是Java利用Phantomjs实现生成图片的功能的详细内容,更多关于JAVA 生成图片的资料请关注随便开发网其它相关文章!

phantomjsjava_Java利用Phantomjs实现生成图片的功能相关推荐

  1. 利用phantomjs动态生成图片

    好记忆不如烂笔头,能记下点东西,就记下点,有时间拿出来看看,也会发觉不一样的感受. 目录 一.问题 二.可行方案 三具体实施: 1.phantomjs 安装运行 2.查找echarts图片 3.生成图 ...

  2. php可以打印一个页面,利用html实现分页打印功能的实例详解

    本篇介绍利用html实现分页打印功能的实例详解,有些不想打印出来的分页打印的都可以应用这类样式进行控制 在非打印时是无效的. 页面打印 /* 应用这个样式的在打印时隐藏 */ .noPrint { d ...

  3. redisson的锁的类型_绝对干货:利用redisson完成分布式锁功能

    在单体架构中,我们使用synchronize或者Lock就能完成上锁同步的操作,但是这些在分布式,微服务的今天,失去了作用. 分布式锁的实现一般有三种解决方案:基于数据库表实现 基于缓存实现,比如re ...

  4. android mysql 搜索功能_android利用数据库实现搜索联想功能

    [实例简介] android利用数据库实现搜索联想功能.主要实现的效果是和google百度搜索一样,实现联想功能. [实例截图] [核心代码] 4e431bd8-d287-4028-8476-7510 ...

  5. java 实现网络通信_利用Java怎么样实现网络通信功能

    利用Java怎么样实现网络通信功能 发布时间:2020-11-20 15:19:04 来源:亿速云 阅读:72 作者:Leah 利用Java怎么样实现网络通信功能?相信很多没有经验的人对此束手无策,为 ...

  6. 我的Android进阶之旅------Android利用Sensor(传感器)实现水平仪功能的小例

    这里介绍的水平仪,指的是比较传统的气泡水平仪,在一个透明圆盘内充满液体,液体中留有一个气泡,当一端翘起时,该气泡就会浮向翘起的一端.    利用方向传感器返回的第一个参数,实现了一个指南针小应用.   ...

  7. python基于opencv的手势识别_怎么在Python3.5 中利用OpenCV实现一个手势识别功能

    怎么在Python3.5 中利用OpenCV实现一个手势识别功能 发布时间:2020-12-22 11:56:32 来源:亿速云 阅读:67 作者:Leah 怎么在Python3.5 中利用OpenC ...

  8. mysql xp cmdshell_LOAD语句:利用MSSQL中的xp_cmdshell功能,将指定文件夹下的指定文件,生成mysql的LOAD语句...

    LOAD语句:利用MSSQL中的xp_cmdshell功能,将指定文件夹下的指定文件,生成mysql的LOAD语句 LOAD语句:利用MSSQL中的xp_cmdshell功能,将指定文件夹下的指定文件 ...

  9. 【PHP学习】—利用ajax原理实现登录功能(八)

    [PHP学习]-利用ajax原理实现登录功能(八) 通过学习上篇文章我们发现这种方法存在了一定的缺陷,利用页面跳转,HTML页面访问服务器,要等待服务器响应,账号密码输入错误后,还要回退页面重新输入账 ...

最新文章

  1. 开源中国众包第二波阿里云悬赏项目,总金额30万
  2. this--学习笔记
  3. BZOJ1044: [HAOI2008]木棍分割(dp 单调队列)
  4. mysql 同步 master-slave
  5. Mac terminal终端或iterm2【 ?~?】~两边出现问号、字体有背景色的问题
  6. 【图像边缘检测】基于matlab CNN灰度图像边缘提取【含Matlab源码 490期】
  7. FPGA实现AXI4总线的读写
  8. Beta-VAE论文阅读笔记
  9. 微信小程序实战教程,适合初学者快速入门。
  10. 主流操作系统的开发语言
  11. linux 移动磁盘空间,如何将Linux下移动磁盘空间?
  12. 解决金仓数据库安装时安装VC++2013报错问题:不受信任提供程序信任的根证书中终止
  13. GWA2吉娃兔升級基於事件驅動的緩存處理模塊
  14. 在visio里面插入带圆圈的数字字符。
  15. 北桥(龙芯的北桥主要是amd的 没有内存控制器 内存控制器在龙芯cpu中)
  16. CentOS5.5 安装Mldonkey 3.0.7
  17. 电子计算机显示屏不亮了,电脑显示屏开机亮一下就不亮了怎么回事
  18. 微信自定义菜单java_Java微信公众平台开发(九)--微信自定义菜单的创建实现
  19. 远程红外热成像app
  20. 第03课:怎么针对微服务架构做单元测试?

热门文章

  1. 软件工程模块开发卷宗_软件智能化再进一步,未来人人都能开发软件?
  2. 批处理命令 / cd
  3. linux top交叉编译_Linux 系统下ARM Linux交叉编译环境crosstool工具
  4. Streamy 使用RDBMS
  5. 推荐:一个VS插件——CopySourceAsHtml
  6. 通用测试用例大全(转自——知了.Test)
  7. 了解mysqlpump工具
  8. 应用开发之WinForm开发
  9. java消息推送与接收
  10. ELK日志管理之——elasticsearch部署