你的浏览器不支持canvas

做你害怕做的事情,然后你会发现,不过如此。

Java使用Selenium生成LuckySheet封面图

时间: 作者: 黄运鑫

本文章属原创文章,未经作者许可,禁止转载,复制,下载,以及用作商业用途。原作者保留所有解释权。


使用场景

  • 项目中用到了在线表格LuckySheet,需要增加自动生成封面图的功能
  • 本来前端已经实现在用户保存时生成封面图的功能,但由于LuckySheet使用的项目和位置太多,改为后端统一生成封面图
  • LuckySheet后端保存的是JSON数据,并不能像富文本一样直接生成图片,所以计划通过浏览器渲染页面后再截图来实现此功能

功能实现

安装Chromedriver

  • 先安装谷歌浏览器,并查看浏览器版本
  • 访问https://registry.npmmirror.com/binary.html?path=chromedriver/找到Chrome浏览器版本对应的驱动,下载操作系统对应的压缩包,如果找不到对应版本,则优先使用大版本号相同的
  • 我的测试环境是win10系统,将解压得到的文件chromedriver.exe移动到Chrome浏览器的根目录,我的目录是C:\Program Files (x86)\Google\Chrome\Application

准备LuckySheet页面模板

  • 由于后端存储的是LuckySheetJSON字符串,所以需要html文件来渲染JSON数据,文件内容如下(js和css略):
<!DOCTYPE html>
<html lang="zh">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <link rel="stylesheet" href="./lib/luckysheet/plugins/css/pluginsCss.css" />
  <link rel="stylesheet" href="./lib/luckysheet/plugins/plugins.css" />
  <link rel="stylesheet" href="./lib/luckysheet/css/luckysheet.css" />
  <link rel="stylesheet" href="./lib/luckysheet/assets/iconfont/iconfont.css" />
  <script src="./lib/luckysheet/plugins/js/plugin.js"></script>
  <script src="./lib/luckysheet/luckysheet.umd.js"></script>
  <title>Document</title>
  <style>
    body {
      margin: 0;
    }
  </style>
</head>

<body>
  <div id="luckysheet-view" style="margin:0px;padding:0px;position:absolute;width:100%;height:100%;left: 0px;top: 0px;">
  </div>
  <script>
    //这里使用占位符${data},最终会将${data}替换为后台存储的JSON字符串
    var data = `${data}`
    if (data) {
      try {
        data = JSON.parse(data)
      } catch (error) {
        // data = {}
      }
    }
    var options = {
      container: 'luckysheet-view', // luckysheet为容器id
      lang: 'zh',
      gridKey: 'luckysheet-view',
      showGridLines: true,
      allowEdit: false,
      showinfobar: false, // 是否显示顶部信息栏
      showsheetbar: true, // 是否显示底部sheet页按钮
      showstatisticBar: false, // 是否显示底部计数栏
      sheetBottomConfig: true, // sheet页下方的添加行按钮和回到顶部按钮配置
      userInfo: false, // 右上角的用户信息展示样式
      showstatisticBarConfig: {
        count: true,
        view: true,
        zoom: true
      },
      showtoolbar: false,
      showsheetbarConfig: {
        add: false, // 新增sheet
        menu: false, // sheet管理菜单
        sheet: true // sheet页显示
      },
    }
    if (data) {
      options.data = data
    }
    window.luckysheet.create(options)
  </script>
</body>

</html>

JAVA实现

  • maven依赖如下:
<!--selenium-->
<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-java</artifactId>
    <version>4.7.2</version>
</dependency>
<!--使用hutool工具包,代码更简洁-->
<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.8.11</version>
</dependency>
  • 测试代码如下:
public static void main(String[] args) {
    //设置chromedriver驱动路径
    System.setProperty("webdriver.chrome.driver", "C:\\Program Files (x86)\\Google\\Chrome\\Application\\chromedriver.exe");
    //从数据库获取到的LuckySheet的options.data内容
    String jsonContent = "[{\"name\":\"Sheet1\",\"color\":\"\",剩余内容略... ...";

    //获取模板文件
    File file = new File("D:\\sheet\\template.html");
    //读取模板文件内容
    String template = FileUtil.readUtf8String(file);
    //将占位符${data}替换为JSON字符串
    template = template.replace("${data}", jsonContent);

    try {
        //将内容写入到新文件index.html
        File htmlFile = new File("D:\\sheet\\index.html");
        //创建文件
        if (!htmlFile.exists()) {
            htmlFile.createNewFile();
        }
        FileUtil.writeUtf8String(template, htmlFile);

        //使用浏览器渲染index.html
        ChromeOptions chromeOptions = new ChromeOptions();
        chromeOptions.addArguments("--no-sandbox");//禁用沙箱
        chromeOptions.addArguments("--disable-dev-shm-usage");//禁用开发者shm
        chromeOptions.addArguments("--headless"); //无头浏览器,这样不会打开浏览器窗口

        WebDriver driver = new ChromeDriver(chromeOptions);
        driver.get("file://" + htmlFile.getCanonicalPath());
        //休眠确保页面渲染完成再截图
        Thread.sleep(2000);
        //获取图片
        File srcFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
        System.out.println("图片路径:" + srcFile.getCanonicalPath());
    } catch (Exception e) {
        e.printStackTrace();
    }
}

对于本文内容有问题或建议的小伙伴,欢迎在文章底部留言交流讨论。