Java之——Java实现网页截屏功能(图片下载功能)的几种方式(整理)

标签: Java
31人阅读 评论(0) 收藏 举报
分类:

转载请注明出处:https://blog.csdn.net/l1028386804/article/details/79955398

最近的项目中,需要实现一个将网页中显示的内容导出为图片的功能,故研究了一下可以实现这个功能的各种方式,整理在此,以供以后使用。

前台方式

1. 利用html2canvas实现前台截屏

html2canvas项目的gitHub地址
html2canvas示例

html2canvas可以将HTML代码块进行截取,并生成快照形式的canvas,然后可以利用html5的下载功能提供图片的下载接口,供用户下载。

优点:前台技术,实现比较容易。

缺点:此项目使用了html5的技术,因此在对IE的兼容上,只可以在IE9+的版本上使用。

使用时,需要引用jQuery.js和html2canvas.js。(html2canvas.js可以在github上下载)

具体JavaScript代码如下:

var canvas = function () {
    html2canvas($("#chart"), {
              onrendered: function (canvas) {
                  $("#class11").html(canvas);//将id为“class11”部分的代码转换为canvas
                  var type = 'png';//图片类型为png
                  var imgData = canvas.toDataURL('png');//将图片转换为png类型的流

                  var _fixType = function (type) {
                      type = type.toLowerCase().replace(/jpg/i, 'jpeg');
                      var r = type.match(/png|jpeg|bmp|gif/)[0];
                      return 'image/' + r;
                  };

                  var saveFile = function (data, filename) {
                      var save_link = document.createElementNS('http://www.w3.org/1999/xhtml', 'a');
                      save_link.href = data;
                      save_link.download = filename;

                      var event = document.createEvent('MouseEvents');
                      event.initMouseEvent('click', true, false, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
                      save_link.dispatchEvent(event);
                  };

                  //下载时的文件名
                  var filename = 'baidufe_' + (new Date()).getTime() + '.' + type;

                  // 下载文件
                  saveFile(imgData, filename);
              }
          });
};

后台方式(java)

1. 利用html2image实现

html2image的地址(google)
html2image是可以识别html标签并将html转换成图片的java项目。

优点:后台转换,故对浏览器的版本基本没有要求。

缺点:对样式的识别不是很好,转换出来的图片比较简单,基本没有可以兼容的样式。

使用方式:maven中引用如下依赖:

<dependency>
  <groupId>com.github.xuwei-k</groupId>
  <artifactId>html2image</artifactId>
  <version>0.1.0</version>
</dependency>

2. 利用DJNativeSwing项目实现

纯java代码实现。使用DJNativeSwing这个项目,构建一个swing浏览器,打开网址,之后截取图片。(需要eclipse的swt库支持)

优点:纯java实现。

缺点:需要多线程的支持,只在控制台方式实现过

使用这个方法,需要引用的maven依赖如下:

<dependency>
    <groupId>com.hynnet</groupId>
    <artifactId>DJNativeSwing</artifactId>
    <version>1.0.0</version>
</dependency>

<dependency>
    <groupId>com.hynnet</groupId>
    <artifactId>DJNativeSwing-SWT</artifactId>
    <version>1.0.0</version>
</dependency>

<dependency>                            
	<groupId>org.eclipse.swt.org.eclipse.swt.win32.win32.x86_64.4.3.swt</groupId>
    <artifactId>org.eclipse.swt.win32.win32.x86_64</artifactId>
    <version>4.3</version>
</dependency>
实现代码如下(引用自http://blog.csdn.net/buddyuu/article/details/52699997):
public class PrintScreen4DJNativeSwingUtils extends JPanel {

    private static final long serialVersionUID = 1L;
    // 行分隔符
    final static public String LS = System.getProperty("line.separator", "/n");
    // 文件分割符
    final static public String FS = System.getProperty("file.separator", "//");
    // 当网页超出目标大小时 截取
    final static public int maxWidth = 2000;
    final static public int maxHeight = 1400;

    /**
     * @param file
     *            预生成的图片全路径
     * @param url
     *            网页地址
     * @param width
     *            打开网页宽度 ,0 = 全屏
     * @param height
     *            打开网页高度 ,0 = 全屏
     * @return boolean
     */
    public PrintScreen4DJNativeSwingUtils(final String file, final String url, final String WithResult) {
        super(new BorderLayout());
        JPanel webBrowserPanel = new JPanel(new BorderLayout());
        final JWebBrowser webBrowser = new JWebBrowser(null);
        webBrowser.setBarsVisible(false);
        webBrowser.navigate(url);
        webBrowserPanel.add(webBrowser, BorderLayout.CENTER);
        add(webBrowserPanel, BorderLayout.CENTER);
        JPanel panel = new JPanel(new FlowLayout());
        webBrowser.addWebBrowserListener(new WebBrowserAdapter() {
            // 监听加载进度
            public void loadingProgressChanged(WebBrowserEvent e) {
                // 当加载完毕时
                if (e.getWebBrowser().getLoadingProgress() == 100) {
                    String result = (String) webBrowser.executeJavascriptWithResult(WithResult);
                    int index = result == null ? -1 : result.indexOf(":");
                    NativeComponent nativeComponent = webBrowser.getNativeComponent();
                    Dimension originalSize = nativeComponent.getSize();
                    Dimension imageSize = new Dimension(Integer.parseInt(result.substring(0, index)),
                            Integer.parseInt(result.substring(index + 1)));
                    imageSize.width = Math.max(originalSize.width, imageSize.width + 50);
                    imageSize.height = Math.max(originalSize.height, imageSize.height + 50);
                    nativeComponent.setSize(imageSize);
                    BufferedImage image = new BufferedImage(imageSize.width, imageSize.height,
                            BufferedImage.TYPE_INT_RGB);
                    nativeComponent.paintComponent(image);
                    nativeComponent.setSize(originalSize);
                    // 当网页超出目标大小时
                    if (imageSize.width > maxWidth || imageSize.height > maxHeight) {
                        // 截图部分图形
                        image = image.getSubimage(0, 0, maxWidth, maxHeight);
                        // 此部分为使用缩略图
                        /*
                         * int width = image.getWidth(), height = image
                         * .getHeight(); AffineTransform tx = new
                         * AffineTransform(); tx.scale((double) maxWidth /
                         * width, (double) maxHeight / height);
                         * AffineTransformOp op = new AffineTransformOp(tx,
                         * AffineTransformOp.TYPE_NEAREST_NEIGHBOR); //缩小 image
                         * = op.filter(image, null);
                         */
                    }
                    try {
                        // 输出图像
                        ImageIO.write(image, "jpg", new File(file));
                    } catch (IOException ex) {
                        ex.printStackTrace();
                    }
                    // 退出操作
                    System.exit(0);
                }
            }
        });
        add(panel, BorderLayout.SOUTH);

    }

    // 以javascript脚本获得网页全屏后大小
    public static String getScreenWidthHeight() {

        StringBuffer jsDimension = new StringBuffer();
        jsDimension.append("var width = 0;").append(LS);
        jsDimension.append("var height = 0;").append(LS);
        jsDimension.append("if(document.documentElement) {").append(LS);
        jsDimension.append("  width = Math.max(width, document.documentElement.scrollWidth);").append(LS);
        jsDimension.append("  height = Math.max(height, document.documentElement.scrollHeight);").append(LS);
        jsDimension.append("}").append(LS);
        jsDimension.append("if(self.innerWidth) {").append(LS);
        jsDimension.append("  width = Math.max(width, self.innerWidth);").append(LS);
        jsDimension.append("  height = Math.max(height, self.innerHeight);").append(LS);
        jsDimension.append("}").append(LS);
        jsDimension.append("if(document.body.scrollWidth) {").append(LS);
        jsDimension.append("  width = Math.max(width, document.body.scrollWidth);").append(LS);
        jsDimension.append("  height = Math.max(height, document.body.scrollHeight);").append(LS);
        jsDimension.append("}").append(LS);
        jsDimension.append("return width + ':' + height;");

        return jsDimension.toString();
    }

    public static boolean printUrlScreen2jpg(final String file, final String url, final int width, final int height) {

        NativeInterface.open();
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                String withResult = "var width = " + width + ";var height = " + height + ";return width +':' + height;";
                if (width == 0 || height == 0)
                    withResult = getScreenWidthHeight();

                JFrame frame = new JFrame("网页截图");
                // 加载指定页面,最大保存为640x480的截图
                frame.getContentPane().add(new PrintScreen4DJNativeSwingUtils(file, url, withResult),
                        BorderLayout.CENTER);
                frame.setSize(640, 480);
                // 仅初始化,但不显示
                frame.invalidate();

                frame.pack();
                frame.setVisible(false);
            }
        });
        NativeInterface.runEventPump();

        return true;
    }

    public static void main(String[] args) {  

        PrintScreen4DJNativeSwingUtils.printUrlScreen2jpg("1122.jpg", "https://www.baidu.com", 1400, 900);

    }
}

3. 利用phantomJs实现

phantomJs的GitHub地址
phantomJs官网

phantom利用的是webKit内核,全面支持web而不需浏览器支持,快速,原生支持各种Web标准。

优点:速度快,使用简单。

缺点:需要在项目的服务器端引用exe文件进行截图,并发性能有待考证。

使用这个方式,需要去官网下载最新的phantomJs脚本。官网地址在上面的链接中。

具体代码如下(引用自http://www.cnblogs.com/lekko/p/4796062.html):

/**
 * 网页转图片处理类,使用外部CMD
 */
public class PhantomTools {

    private static final Logger _logger = Logger.getLogger(PhantomTools.class);

    private static final String _tempPath = "D:/data/temp/phantom_";
    private String basePath;
    private static final String _shellCommand1 = "phantomjs ";
    private static final String _shellCommand2 = "rasterize.js ";

    private String _file;
    private String _size;

    /**
     * 构造截图类
     * @param hash 用于临时文件的目录唯一化
     * @param basePath phantomJs所在路径
     */
    public PhantomTools(int hash, String basePath) {
        _file = _tempPath + hash + ".png";
        this.basePath = basePath;
    }

    /**
     * 构造截图类
     * @param hash 用于临时文件的目录唯一化
     * @param size 图片的大小,如800px*600px(此时高度会裁切),或800px(此时 高度最少=宽度*9/16,高度不裁切)
     * @param basePath phantomJs所在路径
     */
    public PhantomTools(int hash, String size, String basePath) {
        _file = _tempPath + hash + ".png";
        if (size != null)
            _size = " " + size;
        this.basePath = basePath;
    }

    /**
     * 将目标网页转为图片字节流
     * @param url 目标网页地址
     * @return 字节流
     */
    public byte[] getByteImg(String url) throws IOException {
        BufferedInputStream in = null;
        ByteArrayOutputStream out = null;
        File file = null;
        byte[] ret = null;
        try {
            if (exeCmd(basePath + _shellCommand1 + basePath + _shellCommand2 + url + " " + _file + (_size != null ? _size : ""))) {
                file = new File(_file);
                if (file.exists()) {
                    out = new ByteArrayOutputStream();
                    byte[] b = new byte[5120];
                    in = new BufferedInputStream(new FileInputStream(file));
                    int n;
                    while ((n = in.read(b, 0, 5120)) != -1) {
                        out.write(b, 0, n);
                    }
                    file.delete();
                    ret = out.toByteArray();
                }
            } else {
                ret = new byte[] {};
            }
        } finally {
            try {
                if (out != null) {
                    out.close();
                }
            } catch (IOException e) {
                _logger.error(e);
            }
            try {
                if (in != null) {
                    in.close();
                }
            } catch (IOException e) {
                _logger.error(e);
            }
            if (file != null && file.exists()) {
                file.delete();
            }
        }
        return ret;
    }

    /**
     * 执行CMD命令
     */
    private static boolean exeCmd(String commandStr) {
        BufferedReader br = null;
        try {
            Process p = Runtime.getRuntime().exec(commandStr);
            if (p.waitFor() != 0 && p.exitValue() == 1) {
                return false;
            }
        } catch (Exception e) {
            _logger.error(e);
        } finally {
            if (br != null) {
                try {
                    br.close();
                } catch (Exception e) {
                    _logger.error(e);
                }
            }
        }
        return true;
    }
}

查看评论

Spring核心功能指南

-
  • 1970年01月01日 08:00

Java实现网页截屏功能(图片下载功能)的几种方式(整理)

最近的项目中,需要实现一个将网页中显示的内容导出为图片的功能,故研究了一下可以实现这个功能的各种方式,整理在此,以供以后使用。...
  • wanglq0086
  • wanglq0086
  • 2017-03-07 13:11:36
  • 6579

Java实现网页截屏

代码如下 package com.util; import java.awt.AWTException; import java.awt.Desktop; import java.awt.Dime...
  • wenzhilanyu2012
  • wenzhilanyu2012
  • 2015-06-16 21:07:34
  • 1690

web截屏功能的实现

1.提示用户安装activex控件(推荐一款比较好的控件:乖乖牛,主页地址:http://www.ggniu.cn/,具体使用方法可加他们群下载使用文档) 2.如果使用chrome浏览器,那么jque...
  • u011500781
  • u011500781
  • 2016-05-03 13:26:40
  • 2104

纯Java实现整个网页截图项目源代码

  • 2013年12月12日 20:25
  • 3.53MB
  • 下载

基于java的后台截图功能的实现

项目背景:                 近期开发的项目中,需要做到后台将一个url路径作为参数传入,后台生成一幅图片。说白了,其实就是后台跑一个浏览器。在服务器上默默的运行。 在项目的开发后期,我...
  • u014756827
  • u014756827
  • 2015-03-16 11:27:05
  • 1485

android实现截图功能

原文地址:http://blog.csdn.net/hk_256/article/details/7306590 ,转载请注明出处 一、基本介绍            在...
  • g19920917
  • g19920917
  • 2014-04-12 11:54:13
  • 6927

利用Java代码实现图片的下载:

导论: JavaWeb下载文件一般分为两类,其中一类例如.txt,.excel,.zip等浏览器可以识别的文件类型,可以利用标签的链接实现,但是图片的下载确比较麻烦,当使用链接时,浏览器不识别图...
  • qq_36494506
  • qq_36494506
  • 2017-10-10 00:39:32
  • 695

Android中实现截图的几种方式

一、起始原因 最近项目需求中需要实现屏幕截图,开启了新一轮的翻腾,找寻。是的,我就是一个搬运工,简单的搬运工~~做不完的功能,连接不断地需求~~ 基本需求:实现当前页面截图并保存;...
  • u013205623
  • u013205623
  • 2017-03-08 15:45:11
  • 2671

【Android】实现截屏功能

1.截屏功能在像QQ等软件中我们有所
  • u010119170
  • u010119170
  • 2014-07-29 02:22:03
  • 1361
    个人资料
    专栏达人 持之以恒
    等级:
    访问量: 239万+
    积分: 2万+
    排名: 209
    博客专栏
    MySQL

    文章:136篇

    阅读:314741
    Hadoop生态

    文章:149篇

    阅读:237152
    Java

    文章:162篇

    阅读:598579
    J2EE

    文章:76篇

    阅读:311845
    JVM

    文章:18篇

    阅读:55633
    Linux

    文章:85篇

    阅读:257008
    Web前端

    文章:22篇

    阅读:93993
    Mycat

    文章:20篇

    阅读:32101
    设计模式

    文章:22篇

    阅读:52778
    Memcached

    文章:9篇

    阅读:53794
    Redis

    文章:18篇

    阅读:107916
    Netty

    文章:1篇

    阅读:2312
    JMS

    文章:13篇

    阅读:13642
    Dubbo

    文章:20篇

    阅读:57652
    Nginx

    文章:21篇

    阅读:67483
    搜索优化

    文章:24篇

    阅读:28769
    Python

    文章:55篇

    阅读:45764
    Android

    文章:80篇

    阅读:255312
    算法

    文章:1篇

    阅读:648
    MongoDB

    文章:29篇

    阅读:1319
    最新评论