JAVA服务端实现页面截屏(附代码)

news2025/7/16 6:26:43

JAVA服务端实现页面截屏

    • 适配需求
    • 方案一、使用JxBrowser
      • 使用步骤:
    • 方案二、JavaFX WebView
      • 使用步骤:
    • 方案三、Headless Chrome
      • 使用步骤:
    • 综上方案对比
    • 记录我的一个失败方案
    • 参考

适配需求

  1. 有正确完整的地址url;
  2. 通过浏览器能打开该url对应页面;
  3. 需要后台可以自动‘截屏’该页面;
  4. ‘截屏’后的页面可以输出文件(如pdf、png)格式;

方案一、使用JxBrowser

简介 :JxBrowser 具有多进程架构。 它在独立的本地进程中运行 Chromium,这些进程通过进程间通信 (IPC) 通道以光速与 Java 进行通信。 如果 Chromium 中出现错误,您的 Java 进程将保持活动状态。 这一切都与良好的用户体验和用户数据安全有关。​

架构逻辑如下
在这里插入图片描述

使用步骤:

  1. 先申请获得30天免费使用秘钥,也可以直接付费地址
  2. 获取 支持的Jar 包:
  3. Coding :
import static com.teamdev.jxbrowser.engine.RenderingMode.OFF_SCREEN;
import static com.teamdev.jxbrowser.print.PaperSize.ISO_A4;

import com.teamdev.jxbrowser.browser.Browser;
import com.teamdev.jxbrowser.browser.callback.PrintCallback;
import com.teamdev.jxbrowser.browser.callback.PrintHtmlCallback;
import com.teamdev.jxbrowser.browser.callback.SaveAsPdfCallback;
import com.teamdev.jxbrowser.browser.event.PrintPreviewOpened;
import com.teamdev.jxbrowser.engine.Engine;
import com.teamdev.jxbrowser.engine.EngineOptions;
import com.teamdev.jxbrowser.engine.RenderingMode;
import com.teamdev.jxbrowser.frame.Frame;
import com.teamdev.jxbrowser.print.PdfPrinter;
import com.teamdev.jxbrowser.print.PrintJob;
import com.teamdev.jxbrowser.print.event.PrintCompleted;
import java.nio.file.Path;
import java.nio.file.Paths;

public class JxBrowserDemo {
    // 构造一个浏览器实例
    public JxBrowserDemo() {
        // 设置证书秘钥
        System.setProperty("jxbrowser.license.key", "此处略");
    }
    // 执行方法
    public void run(String url) {
        EngineOptions engineOptions = EngineOptions.newBuilder(OFF_SCREEN).build();
        // 初始化 Chromium 引擎
        Engine engine = Engine.newInstance(engineOptions);
        // 创建一个浏览器实例
        Browser browser = engine.newBrowser();
        // 等待加载url完成
        browser.navigation().loadUrlAndWait(url);
        // 打印网络页面
        browser.mainFrame().ifPresent(frame -> System.out.println(frame.html()));
        browser.set(PrintCallback.class, (params, tell) -> {
            tell.print();
        });
        // 设置pdf文件导出位置
        browser.set(PrintHtmlCallback.class, (params, tell) -> {
            Path path = Paths.get("/Users/*****/temp3.pdf");
            PdfPrinter<PdfPrinter.HtmlSettings> printer = params.printers().pdfPrinter();
            PrintJob<PdfPrinter.HtmlSettings> printJob = printer.printJob();
            printJob.settings()
                    .paperSize(ISO_A4)
                    .enablePrintingBackgrounds()
                    .pdfFilePath(path)
                    .apply();
            printJob.on(PrintCompleted.class, event -> {
                if (event.isSuccess()) {
                    System.out.println("Printing is completed successfully.");
                } else {
                    System.out.println("Printing has failed.");
                }
            });
            tell.proceed(printer);
        });
        browser.mainFrame().ifPresent(frame -> {
            frame.print();
        });
        try {
            Thread.sleep(100000);
        }catch (InterruptedException e) {
            // do nothing
        }
        // 关闭引擎释放资源
        engine.close();
    }
}

方案二、JavaFX WebView

JavaFX WebView 是在 2014 年成为 JDK 8 的一部分的 JavaFX 2.0 中引入的。
如果您使用 Java 8,那么您不需要做任何特别的事情来开始使用 JavaFX WebView。
使用JDK 11及更高版本的JavaFX不再捆绑,因此要使用JavaFX 11或更高版本进行开发,您必须单独下载。

JavaFX在您的Java进程中初始化并运行WebKit。JavaFX允许您非常快速地创建和显示WebView。
然而WebKit会分配和使用Java进程的内存和CPU,一些现代网页可能会分配超过1GB的RAM。
您创建和加载网页的WebView实例越多,Java应用程序的RAM就越多(耗内存)。
在这里插入图片描述

使用步骤:

不需要额外操作直接coding即可
Coding :

import javafx.application.Application;
import javafx.embed.swing.SwingFXUtils;
import javafx.geometry.HPos;
import javafx.geometry.VPos;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.image.WritableImage;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import javafx.scene.layout.Region;
import javafx.scene.paint.Color;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import javax.imageio.ImageIO;
import java.awt.image.RenderedImage;
import java.io.File;
import java.io.IOException;

// 需要继承 javafx.application.Application
public class JavaFxDemo extends Application {
    private Scene scene;
    @Override
    public void start(Stage stage) throws Exception {
        // 创建画布
        stage.setTitle("Web View");
        // 设置场景
        scene = new Scene(new Browser(), 750, 500, Color.web("#666970"));
        stage.setScene(scene);
        // 风格样式
        scene.getStylesheets().add("webviewsample/BrowserToolbar.css");
        stage.show();
    }
}
// 需要继承 Region
class Browser extends Region {
    final WebView browser = new WebView();
    // 浏览器引擎
    final WebEngine webEngine = browser.getEngine();
    public Browser() {
        // 浏览器应用风格
        getStyleClass().add("browser");
        // 加载web页面
        webEngine.load("http://www.oracle.com/products/index.html");
        // 页面增加到引擎中
        getChildren().add(browser);

    }
    private Node createSpacer() {
        Region spacer = new Region();
        HBox.setHgrow(spacer, Priority.ALWAYS);
        return spacer;
    }
    @Override protected void layoutChildren() {
        double w = getWidth();
        double h = getHeight();
        layoutInArea(browser,0,0,w,h,0, HPos.CENTER, VPos.CENTER);
    }
    @Override protected double computePrefWidth(double height) {
        return 750;
    }
    @Override protected double computePrefHeight(double width) {
        return 500;
    }
}

public class Application {
    public static void main(String[] args) {
        System.out.println("hello, world");
        javaFxDemo.run("https://www.baidu.com");
    }
}

方案三、Headless Chrome

简介:Headless Chrome 是 Chrome 浏览器的无界面形态,可以在不打开浏览器的前提下,使用所有 Chrome 支持的特性运行你的程序。

原理: 通过chromedriver 驱动加载对应页面,可以后台获取截图,并按照文件、字节流等方式返回;

使用步骤:

  1. 下载 chromedriver 和 同版本 的 chrome 到本地 驱动地址;
  2. 放置到系统对应位置(win系统在Windows目录下,Mac在包含bin的目录下),设置好执行权限;
  3. 引入 selenium-server-standalone.jar 依赖
<dependency>
    <groupId>org.seleniumhq.selenium</groupId>
    <artifactId>selenium-java</artifactId>
    <version>3.6.0</version>
</dependency>
  1. Coding :
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;

@Service
public class ScreenshotService {

    private static WebDriver driver;
    @PostConstruct
    private void initDriver(){
        ChromeOptions options = new ChromeOptions();
        /*
         * 这里是设置要执行的命令
         * --headless: 不提供可视化页面(无头模式)
         * --disable-gpu: 禁用GPU加速
         * --window-size: 修改截图页面的尺寸 "--window-size=1920,1200"
         * --ignore-certificate-errors:
         */
        options.addArguments("--headless", "--disable-gpu", "--window-size=1920,1920", "--ignore-certificate-errors");
        options.addArguments("--disable-dev-shm-usage", "--no-sandbox");
        driver = new ChromeDriver(options);
    }

    /**
     * 根据网络url获取网络截屏的字节数组
     * @param url 网络url
     * @return 字节数组
     */
    private static synchronized byte[] getFileByteArry(String url){
        // 1.打印chromedriver驱动
        log.info("[页面抓取]- {}", driver);
        long startTime = System.currentTimeMillis();
        // 2.加载web页面
        driver.get(url);
        // 3.页面等待渲染时长,如果你的页面需要动态渲染数据的话一定要留出页面渲染的时间,单位默认是秒
        new WebDriverWait(driver, 5);
        // 4.获取到截图的文件字节
        byte[] byteArry = ((TakesScreenshot) driver).getScreenshotAs(OutputType.BYTES);
        log.info("[页面抓取]ChromeDriver处理结束用时{}s, Title:{}", calUsedTime(startTime), driver.getTitle());
        return byteArry;
    }
}

【开发过程中我实际遇到的问题】:
1.代码指定浏览器驱动位置无效, 生成驱动时按照系统自动加载:win系统在Windows目录下,Mac在包含bin的目录下;
2.Mac系统中驱动需要权限,Win不需要可权限可直接执行;
3.页面大小设置问题:不提供可视化页面情况下必须指定截图页面尺寸,自上而下自左而右截取(可能有丢失内容风险);
4.如果设置页面渲染超时间(可以去除该设置):默认需要指定加载到页面Element标签ID,如果页面不含该ID则报错;


综上方案对比

JxBrowserJavaFXHeadless
开源否,需付费
依赖第三方包JDKselenium +谷歌驱动
操作复杂,需要申请令牌和增加依赖简单复杂,下载安装驱动和浏览器并增加依赖
代码复杂度简单,依赖包强大稍复杂,需要有抽象和分层概念简单,面向对象概念
耗时快 2-3秒一般 3-5秒慢 4-6秒
页面效果nice一般nice
不足依赖第三方服务无法后台存储,需要弹窗选择执行稍慢

记录我的一个失败方案

思路:通过get请求url获得一个html响应,将html打印获取页面;
失败原因:html需要在线获取一些前端样式(js、css)渲染,如果直接打印可能只是一个空页面。必须要经过web端进行渲染才能实现基本的页面格式。


参考

文章为个人实际开发完成后的技术整理
有相关问题可以参考我当时查资料的参考(帮您节省时间),如下:

JxBrowser
知乎 · 什么是 JxBrowser
JavaFX入门介绍
知乎 · JxBrowser还是JavaFX WebView
CSDN · Headless Chrome
CSDN · 使用ChromeHeadLess

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/363034.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Redis缓存一致性问题(缓存更新策略)

Redis缓存的一致性1. 缓存1.1 缓存的作用&#xff1a;1.2 缓存的成本&#xff1a;2. 缓存模型3. 缓存一致性问题3.1 引入3.2 解决(1) 先更新数据库&#xff0c;再手动删除缓存(2) 使用事务保证原子性(3) 以Redis中的TTL为兜底3.3 案例&#xff1a;商铺信息查询和更新(1) 查询商…

5.12 BGP选路原则综合实验

配置BGP的选路原则 1. 实验目的 熟悉BGP的选路的应用场景掌握BGP的选路的配置方法2. 实验拓扑 实验拓扑如图5-11所示: 图5-11:配置BGP的选路原则 3. 实验步骤 (1)配置IP地址 R1的配置

Spring中自定义Session管理,Spring Session源码解析

系列文章&#xff1a;Spring Boot学习大纲&#xff0c;可以留言自己想了解的技术点 目录 系列文章&#xff1a;Spring Boot学习大纲&#xff0c;可以留言自己想了解的技术点 1、session是什么&#xff1f; 1>session在哪里&#xff1f; 2>服务器怎么知道每次说话的是…

Python + Selenium,分分钟搭建 Web 自动化测试框架!

在程序员的世界中&#xff0c;一切重复性的工作&#xff0c;都应该通过程序自动执行。「自动化测试」就是一个最好的例子。 随着互联网应用开发周期越来越短&#xff0c;迭代速度越来越快&#xff0c;只会点点点&#xff0c;不懂开发的手工测试&#xff0c;已经无法满足如今的…

【Datawhale图机器学习】DeepWalk和Node2Vec

DeepWalk&#xff1a;用于图节点嵌入的在线机器学习算法 论文介绍 DeepWalk是基于随机游走的图节点嵌入算法。首次将深度学习和自然语言处理思想用于图机器学习&#xff0c;将随机游走序列与句子类比&#xff0c;节点与单词类比&#xff0c;构建Word2Vec的Skip-Gram无监督&am…

了解Axios及其运用方式

Axios简介 axios框架全称&#xff08;ajax – I/O – system&#xff09;&#xff1a; 基于promise用于浏览器和node.js的http客户端&#xff0c;因此可以使用Promise API 一、axios是干啥的 说到axios我们就不得不说下Ajax。在旧浏览器页面在向服务器请求数据时&#xff0c;…

计算机网络基础知识

目录 通信基础 前言 广播域与冲突域 计算机之间的连接方式 网线直连&#xff08;交叉线&#xff09; 同轴电缆 集线器 网桥 前言 举例&#xff08;计算机6向计算机7相互通信&#xff09; 交换机 交换机原理 路由器 路由器与其他设备区别&#xff1a; 注意&#…

Docker之路(3.docker底层原理、和虚拟机VM对比区别)

1.docker run 流程图 2. docker 底层原理 2.1 docker 是怎么工作的&#xff1f; Docker 是一个 Client-Server 结构的系统&#xff0c;Docker的守护进程运行在主机上&#xff0c; 通过Socket从客户端访问&#xff01; DockerServer接收到Docker-Client的指令&#xff0c;就会执…

【历史上的今天】2 月 22 日:Red Hat Enterprise Linux 问世;BASIC 语言作者出生;计算机协会创始人诞生

整理 | 王启隆 透过「历史上的今天」&#xff0c;从过去看未来&#xff0c;从现在亦可以改变未来。 今天是 2023 年 2 月 22 日&#xff0c;在 1857 年的今天&#xff0c;德国物理学家海因里希赫兹&#xff08;Heinrich Hertz&#xff09;出生。赫兹于 1887 年首先用实验证实了…

Mysql数据备份

一.数据备份的意义&#xff08;1&#xff09;保护数据的安全&#xff1b;&#xff08;2&#xff09;在出现意外的时候&#xff08;硬盘的损坏&#xff0c;断电&#xff0c;黑客的攻击&#xff09;&#xff0c;以便数据的恢复&#xff1b;&#xff08;3&#xff09;导出生产的数…

【音频处理和分析工具】上海道宁与NUGEN Audio助力您更轻松地提供高质量、合规的音频

NUGEN Audio的产品 可在任何情况下提供 先进的保真度和 不受限制的创造力 提供直接和直观的声音处理方式 NUGEN工具可以更轻松地 提供高质量、合规的音频 同时节省时间 降低成本并保留创作过程 开发商介绍 NUGEN Audio是后期制作、音乐和广播领域的知名品牌&#xff0c…

【Mysql】 锁

【Mysql】 锁 文章目录【Mysql】 锁1. 锁1.1 概述1.2 全局锁1.2.1 介绍1.2.2 语法1.2.2.1 加全局锁1.2.2.2 数据备份1.2.2.3 释放锁1.2.3 特点1.3 表级锁1.3.1 介绍1.3.2 表锁1.3.3 元数据锁1.3.4 意向锁1.4 行级锁1.4.1 介绍1.4.2 行锁1.4.3 间隙锁&临键锁1. 锁 1.1 概述…

一起学习用Verilog在FPGA上实现CNN----(八)integrationFC设计

1 integrationFC设计 LeNet-5网络结构全连接部分如图所示&#xff0c;该部分有2个全连接层&#xff0c;1个TanH激活层&#xff0c;1个SoftMax激活层&#xff1a; 图片来自附带的技术文档《Hardware Documentation》 integrationFC部分原理图&#xff0c;如图所示&#xff0c;…

python基于flask共享单车系统vue

可定制框架:ssm/Springboot/vue/python/PHP/小程序/安卓均可开发 目录 1 绪论 1 1.1课题背景 1 1.2课题研究现状 1 1.3初步设计方法与实施方案 2 1.4本文研究内容 2 2 系统开发环境 4 2. 3 系统分析 6 3.1系统可行性分析 6 3.1.1经济可行性 6 3.1.2技术可行性 6 3.1.3运行可行…

应用层协议

目录 应用层常见协议 DNS协议 前言 域名结构 DNS服务器分类 DNS的工作原理 DNS工作原理实例 DNS记录 DHCP协议 静态IP与动态IP DHCP协议好处 DHCP分配IP地址的4阶段 电子邮件 邮件的过程 电子邮件发送过程 pop协议特点 IMAP协议的特点 FTP协议 前言 FTP数据…

操作系统-初次理解

目录 1. 冯诺依曼体系 2. 操作系统 2.1 概念 2.2 解释 2.3 为什么管理 1. 冯诺依曼体系 我相信大家在学习计算机语言时一定听过这个体系结构的&#xff0c;那么这个结构到底是什么呢&#xff1f;上图&#xff1a; 该图是我对冯诺依曼体系结构简单构造&#xff0c;真实情况更…

Java实现多线程有几种方式(满分回答)

目录JDK8 创建的线程的两种方式orcle文档解释方式一&#xff1a;继承Thread类方式二&#xff1a;实现Runnable接口同时用两种的情况其他间接创建方式Callable接口线程池JDK8 创建的线程的两种方式 orcle文档解释 orcle文档&#xff1a;https://docs.oracle.com/javase/8/docs…

【项目精选】动漫论坛的设计与实现(论文+视频+源码)

点击下载源码 作为文化产业的一部分&#xff0c;动漫影响了我国一代又一代青少年&#xff0c;据钱江晚报调查显示&#xff0c;有超过七成的95后愿意从事与动漫相关的行业&#xff0c;可见其对青少年影响力之大。 动漫论坛作为最先开始热爱动漫人士进行交流的方式之一&#xff0…

让师生“不跑腿”,教育数据治理究竟有何魔力

当前&#xff0c;教育信息化新基础设施正在加紧建设&#xff0c;教育业务系统应用不断推进&#xff0c;各种软硬件平台源源不断地产生着教育数据。海量数据的汇聚和分析&#xff0c;能给教育系统带来什么&#xff1f;如何在教育数字化转型中&#xff0c;探索出基于数据驱动的新…

Linux 浅谈之性能分析工具 perf

Linux 浅谈之性能分析工具 perf HELLO&#xff0c;各位博友好&#xff0c;我是阿呆 &#x1f648;&#x1f648;&#x1f648; 这里是 Linux 浅谈系列&#xff0c;收录在操作系统专栏中 &#x1f61c;&#x1f61c;&#x1f61c; 本系列将记录一些阿呆个人整理的 OS 相关知识…