Java 杂谈

使用phantomjs无界浏览器截图

2018-09-06  本文已影响5人  fkxuexi

一、前言:问题的背景

我之前一直负责一个公众号的项目,老大在别的公众号看到一个功能,可以把自己的盈利记录做一个好看的H5截图分享出去,界面是可以分享出去的,但是如果分享的是一个H5的话,有很多人都懒得点进去,但是如果生成图片的话,把图片分享出去就更加直观也更加吸引人。现在在新媒体盛行的时代,这个应用场景还是很多的,因此今天来介绍一下如何实现。可以关注一下金汇微策略的公众号的最新策略的功能体验,因为我们的公众号只有分析师有这个权限操作。

二、使用的技术:

现在可用的技术:

三、流程:

3.1、所需要的文件:

四、代码

4.1、使用freemarker生成html界面
/**
     * 依据ftl模板来生成html,并返回html的名字和(因为不同的人生成的html的数据是不一致的)
     * 并且返回生成的html的名字
     *
     * @return 返回生成的每个人的html
     */
    public static Map<String,String> generHtml(AnalystShare share) throws IOException, TemplateException, InterruptedException {
        Configuration ftlCfg = new Configuration();
        ftlCfg.setEncoding(Locale.getDefault(),"utf-8");
        ftlCfg.setDirectoryForTemplateLoading(new File(Const.FETCH_SCREEN_DIR));
        Template template = ftlCfg.getTemplate(Const.TEMPLATE_NAME,"utf-8");

        String generHtmlName = System.currentTimeMillis()+".html";
        String generHtmlPath = Const.FETCH_SCREEN_DIR + generHtmlName;
        File file = new File(generHtmlPath);
        if (!file.exists()) {
            file.createNewFile();
        }
        OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(file),"utf-8");
        PrintWriter printWriter = new PrintWriter(writer);
        Map map = new HashMap<>();
        map.put("share", getFormatShare(share));
        template.setEncoding("utf-8");
        template.process(map, printWriter);
        Thread.sleep(2000);
        printWriter.close();
        Map pathMap = new HashMap<String,String>();
        pathMap.put("generHtmlName",generHtmlName);
        pathMap.put("generHtmlPath",generHtmlPath);
        return pathMap;
    }

上面有很多点需要注意:

4.2、生成bat文件或者sh文件
/**
     * 创建bat文件并把bat文件的全路径以及img的全路径全部返回回去
     * @param generHtmlName
     * @return
  */
    public static Map<String, String> generBat(String generHtmlName) throws IOException {
        String batFileName = System.currentTimeMillis()+".bat";
        String batFilePath = Const.FETCH_SCREEN_DIR + batFileName;
        String generImgName = System.currentTimeMillis()+".jpg";
        String generImgPath = Const.FETCH_SCREEN_DIR +generImgName;
        File file = new File(batFilePath);
        FileWriter writer = new FileWriter(file);
        writer.write("e:");
        writer.write(System.getProperty("line.separator"));
        writer.write("cd " + Const.FETCH_SCREEN_DIR );
        writer.write(System.getProperty("line.separator"));
        writer.write("phantomjs.exe phantomjs.js " + generHtmlName + " " + generImgName);
        writer.flush();
        writer.close();
        Map map = new HashMap<String, String>();
        map.put("generBatPath", batFilePath);
        map.put("generImgPath", generImgPath);
        map.put("generImgName",generImgName);
        return map;
    }

上面是生成bat的,sh的命令如下,由于篇幅的原因不在写sh的部分,直接把下面的命令写入到sh文件即可。注意*.html 这个地方要依据你程序生成的HTML的名字为准,上面我是采用毫秒值进行命名的,依据自己的需求进行修改即可,cd的路径也是需要修改的,这里我把所有的文件放在一个目录下。一定要修改成自己实际的文件的名字和目录,下面是我进行本地测试的时候的文件。


image.png
cd /data/wwwroot/default/upload/screen/
./phantomjs phantomjs.js test.html test.png
4.2、执行bat|sh文件
 /**
     * 执行bat文件,生成图片
     * @param batPath
     */
    public static void execute(String batPath) throws IOException, InterruptedException {
        Runtime rt = Runtime.getRuntime();
        Process exec = rt.exec(batPath);
        Thread.sleep(5000);
        exec.destroyForcibly();
        exec.destroy();
        return;
    }
4.3、做善后工作,删除生成的文件
 /***
     * 做完所有的善后的工作,把所有生成的文件delete掉
     * @param htmlPath
     * @param batPath
     * @param imgPath
     */
    public static void destoryAllGenerFile(String htmlPath, String batPath, String imgPath) {
        File file = new File(htmlPath);
        file.deleteOnExit();
        file = new File(batPath);
        file.deleteOnExit();
        file = new File(imgPath);
        file.deleteOnExit();
    }
4.4、phantomjs.js

执行phantomjs脚本,生成快照脚本

/**
 * phantomJs 脚本
 */
var page = require('webpage').create(), system = require('system'), address, output, size;

if (system.args.length < 3 || system.args.length > 5) {
    phantom.exit(1);
} else {
    address = system.args[1];
    output = system.args[2];
    //定义宽高
   /* page.viewportSize = {
        width : 1024,
        height : 768
    };*/
    page.open(address, function(status) {
        var bb = page.evaluate(function() {
            return document.getElementsByTagName('html')[0].getBoundingClientRect();
        });
        page.clipRect = {
            top : bb.top,
            left : bb.left,
            width : bb.width,
            height : bb.height
        };
        window.setTimeout(function() {
            page.render(output);
            page.close();
            console.log('渲染成功...');
            console.log(address);
        }, 1000);
    });
}

ps:由于ftl文件设计到公司的业务,所以不公开出来,依据这个流程大体是可以生成的。下面说下过程中遇到的问题。

上一篇下一篇

猜你喜欢

热点阅读