Java利用Phantomjs实现生成图片的功能

今天,给大家分享一个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 生成图片的资料请关注我们其它相关文章!

时间: 2020-07-31

java生成图片验证码示例代码

本文实例为大家分享了java图片验证码具体实现代码,供大家参考,具体内容如下 import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.image.BufferedImage; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.u

java图片验证码生成教程详解

首先,我们先来看本地如何生成图片验证码的,再来写输出到网页的验证码如何实现. 先来看最简单的-实现的功能是,将一个字符串变成图片写入到文件中 实现代码: package cn.hncu.img; import java.awt.Graphics; import java.awt.image.BufferedImage; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOE

java 生成文字图片的示例代码

本文主要介绍了java 生成文字图片的示例代码,分享给大家,具体如下: import java.awt.Color; import java.awt.Font; import java.awt.FontMetrics; import java.awt.Graphics; import java.awt.Rectangle; import java.awt.image.BufferedImage; import java.io.File; import javax.imageio.ImageIO;

利用weixin-java-miniapp生成小程序码并直接返回图片文件流的方法

有时候我们可能需要在其他的网页上展示我们自己的小程序中某些页面的小程序码,这种时候,我们需要用到小程序的生成小程序码的相关接口. 工具选型 我们仍然选用简单方便的weixin-java-miniapp来完成此功能. 项目配置 详见我们的另一篇文章点此进入 生成小程序码的相关类型 小程序码的其他生成方式以及相关类型在这篇文章点此进入中介绍的较为详细,此处不再赘述,以下仅以生成不限制张数的这种类型来做一个示例. 生成小程序码图片 先获取小程序的service实例wxMaService. 再获取二维码

Java 生成图片验证码3种方法(字母、加减乘除、中文)

第一种方法 全是字母和数字组成 package com.myFirstSpring.util; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.Random; import javax.imageio.ImageIO; import java

java poi设置生成的word的图片为上下型环绕以及其位置的实现

问题描述 在使用poi-tl word模版工具时,发现生成的文档中,图片格式为嵌入型,有的图片甚至被表格遮挡一半.而自己想要的图片格式为上下型环绕,并且图片需要居中. 问题分析 poi-tl渲染图片,使用的是org.apache.poi.xwpf.usermodel.XWPFRun的addPicture方法,该方法中有一段代码:CTInline inline = drawing.addNewInline();意思就是默认将图片转为inline类型,即行内元素. 然后我们把生成的嵌入型图片的文档转

Java PhantomJs完成html图片输出功能

借助phantomJs来实现将html网页输出为图片 I. 背景 如何在小程序里面生成一张图,分享到朋友圈呢?目前前端貌似没有太好的解决方法,所以只能猥琐的由后端来支持掉,那么可以怎么玩? 生成图片比较简单 简单的场景,可以直接用jdk来支持掉,一般来讲也没有太复杂的逻辑 之前写过一个图片合成的逻辑,利用awt实现: 图片合成 通用.复杂的模板 简单的可以直接支持,但复杂一点的,让后端来支持,无疑比较恶心,在github上也搜索了一些渲染html的开源库,不知道是姿势不对还是咋的,没有太满意的结

java利用phantomjs进行截图实例教程

前言 最近工作中遇到一个需求,需要实现截图功能,断断续续查找资料.验证不同的实现方法终于算基本搞定了页面截图,因为中间过程曲折花费较多时间,分享出来帮助大家快速实现截图 为什么选用phantomjs进行截图 截图可以实现的方式有很多,比如: selenium HtmlUnit Html2Image...and so on但是这些实现的截图效果都不好.selenium只能实现截屏,不能截取整个页面,而HtmlUnit.Html2Image对js的支持效果并不好,截下来的图会有很多空白.phanto

java生成图片验证码功能

最近在用ssm框架做一个管理系统,做到登录验证时,使用了下面的代码生成图片验证码,最终的效果如下图. Java类 public class RandomValidateCode { public static final String RANDOMCODEKEY = "randomcode_key";//放到session中的key private Random random = new Random(); private String randString = "01234

Java生成验证码功能实例代码

页面上输入验证码是比较常见的一个功能,实现起来也很简单.给大家写一个简单的生成验证码的示例程序,需要的朋友可以借鉴一下. 闲话少续,直接上代码.代码中的注释很详细. package com.SM_test.utils; import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.RenderingHints; import ja

java生成图片验证码实例代码

关于java图片验证码的文章最近更新了不少,帮助大家掌握java验证码的生成技术,下文为大家分享了java生成图片验证码最简单的方法,供大家参考. 现在各行业在定制系统时都会考虑到机器注册,现在最有效的方式就是输入验证.现在的验证方式有很多种: 一.问题验证,其实也是图片验证,在图片上生成问题,然后输入框输入答案. 二.图片验证,输入图片上展示的文字信息. 三.短信验证,比较繁杂,用户也不怎么喜欢. 四.还有就是百度最新的验证方式.图片上生成文字,然后出现一个文字点击框,选择你在验证图片上看到的

PHP生成图片验证码功能示例

本文实例讲述了PHP生成图片验证码功能.分享给大家供大家参考,具体如下: 只是简单的用随机函数实现了图片的生成,没有对验证的整个流程做介绍. 代码如下: <?php /** * Created by JetBrains PhpStorm. * User: lee * To change this template use File | Settings | File Templates. */ header("content-type:image/png"); $validate

java生成图片验证码示例程序

复制代码 代码如下: <%@ page language="java" contentType="text/html; charset=UTF-8"    pageEncoding="UTF-8"%><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8">&l

Java实现验证码具体代码(图片、汉字)

本文为大家分享两个实例,相信大家一定会喜欢. 实例1:随机生成验证码图片并将之输出为一个png文件 效果图: import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.util.Random; import javax.

java实现验证码小程序

手动制作java的验证码,具体内容如下 Web应用验证码的组成: (1)输入框 (2)显示验证码的图片 验证码的制作流程: 生成验证码的容器使用 j2ee的servlet 生成图片需要的类: (1) BufferedImage 图像数据缓冲区 (2)Graphic绘制图片 (3)Color获取颜色 (4)Random生成随机数 (5)ImageIO输入图片 具体实现流程: (1)定义一个Servlet,用于生成验证码 (2)定已BufferedImage对象,主要作用就是制作一个图片缓冲区,作为

Java如何随机生成图片验证码

本文实例为大家分享了Java随机生成图片验证码的具体代码,供大家参考,具体内容如下 首先使用一下代码 可生成 一张指定文理和字体的验证码 package xxy.image; import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import java.awt.image.BufferedImage; import java.io.FileNotFoundException; import java.io