当前位置: 首页 > news >正文

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

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;@Overridepublic 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;@PostConstructprivate 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

相关文章:

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

JAVA服务端实现页面截屏适配需求方案一、使用JxBrowser使用步骤&#xff1a;方案二、JavaFX WebView使用步骤&#xff1a;方案三、Headless Chrome使用步骤&#xff1a;综上方案对比记录我的一个失败方案参考适配需求 有正确完整的地址url&#xff1b;通过浏览器能打开该url对…...

Java入门要知道!

首先我们都知道的是Java是一门面向对象的编程语言&#xff0c;不仅吸收了C语言的各种优点&#xff0c;还摒弃了C里难以理解的多继承、指针等概念&#xff0c;因此Java语言具有功能强大和简单易用两个特征。Java语言作为静态面向对象编程语言的代表&#xff0c;极好地实现了面向…...

[6/101] 101次软件测试面试之经典面试题剖析

01、自我介绍答&#xff1a;大家好&#xff0c;我是一名软件测试工程师&#xff0c;但我更喜欢称自己为“软件bug捕手”。我相信&#xff0c;软件测试工程师的使命就是让软件更加健壮、更加可靠、更加美好。我们就像是一群“特警”&#xff0c;在黑暗的代码中寻找漏洞和缺陷&am…...

电脑c盘满了变成红色了怎么清理,清理c盘详细攻略

我们的电脑当用了一段时间之后&#xff0c;其实自然而然的就会有一点点卡&#xff0c;其实这是因为我们的电脑c盘满了&#xff0c;所以会造成卡顿是正常的&#xff0c;今天我们就来聊一聊电脑c盘满了变成红色了怎么清理&#xff1f; 一.电脑c盘为啥会满 软件安装&#xff1a;当…...

现在的00后,实在是太卷了

现在的小年轻真的卷得过分了。前段时间我们公司来了个00年的&#xff0c;工作没两年&#xff0c;跳槽到我们公司起薪18K&#xff0c;都快接近我了。后来才知道人家是个卷王&#xff0c;从早干到晚就差搬张床到工位睡觉了。 最近和他聊了一次天&#xff0c;原来这位小老弟家里条…...

RocketMQ概述

RocketMQ入门学习MQ概述MQ简介MO用途限流削峰异步解耦数据收集常见的MQ产品ActiveMQRabbitMQKafkaRocketMQ对比MQ常见协议JMSSTOMPAMOPMQTTMQ概述 MQ简介 MQ&#xff0c;Message Queue&#xff0c;是一种提供消息队列服务的中间件&#xff0c;也称为消息中间件&#xff0c;是…...

解决Ubuntu22.04.1上安装ch34x串口驱动报 Key was rejected by service 需要签名的问题

解决Ubuntu22.04.1上安装ch34x串口驱动报 Key was rejected by service 需要签名的问题问题官网下载解压驱动包编译安装给驱动签名再来载入模块&#xff08;设备驱动程序&#xff09;问题 Ubuntu22.04.1 Linux版本5.19.0-32-generic 运行Qt串口通信 m_serialPort->open(QIO…...

[python入门㊿] - python如何打断点

目录 ❤ 什么是bug(缺陷) ❤ python代码的调试方式 ❤ 使用 pdb 进行调试 测试代码示例 利用 pdb 调试 退出 debug debug 过程中打印变量 停止 debug 继续执行程序 debug 过程中显示代码 使用函数的例子 对函数进行 debug 在调试的时候动态改变值 ❤ 使用 PyC…...

CCNP350-401学习笔记(501-550题)

501、Refer to the exhibit. What is the effect of the configuration? A. The device will allow users at 192.168.0.202 to connect to vty lines 0 through 4 using the password ciscotestkey B. The device will allow only users at 192 168.0.202 to connect to vty …...

音箱上8键触摸芯片绿芯GTC08L完美替换启攀微

由工采网代理提供的韩国GreenChip电容式触摸芯片-GTC08L是GreenTouch5CTM电容式触摸传感器系列之一&#xff1b;可以在发动机运行下进行8通道电容传感&#xff1b;对电磁兼容、电磁干扰、温湿度变化、电压干扰、温度漂移、湿度漂移等都有较强的抗干扰能力。不会对CS, RS,EFT&am…...

php+vue加油站会员服务系统 java微信小程序

目 录 1绪论 1 1.1项目研究的背景 1 1.2开发意义 1 1.3项目研究现状及内容 5 1.4论文结构 5 2开发技术介绍 7 2.5微信小程序技术 8 3系统分析 9 3.1可行性分析 9 3.1.1技术可行性 9 3.1.2经济可行性 9 3.1.3操作可行性 10 3.2网站性能需求分析 10 3.3网站功能分析 10 3.4系统…...

ES6--class类(详解/看完必会)

目录 1、基本概念 2、基本用法 3、class与构造函数的区别 4、constructor的使用 5、自定义方法 6、extends和super &#xff08;1&#xff09;问题一&#xff1a;我们想要在点击按钮二的时候改变字体大小&#xff0c;如何写呢&#xff1f; &#xff08;2&#xff09;问…...

ChatGPT的出现网络安全专家是否会被替代?

ChatGPT的横空出世&#xff0c;在业界掀起了惊涛骇浪。很多人开始担心&#xff0c;自己的工作岗位是否会在不久的将来被ChatGPT等人工智能技术所取代。网络安全与先进技术发展密切相关&#xff0c;基于人工智能的安全工具已经得到很多的应用机会&#xff0c;那么未来是否更加可…...

游戏服务器框架设计 总纲

服务器框架篇&#xff1a; 1.配置文件系统 libxml 2.日志系统 log4xx 3.数据库保存以及接口设计 4.Proto协议定义 5.Redis接口设计 6.网络层设计 epoll/iocp 7.服务器内部协议路由层设计 8.分布式节点管理设计 9.服务器负载伸缩管理设计 10.服务器进程热更流程设计 11.GM系…...

PB里post提交

PB 通过 PostRul 一、 创建Standard Class对象 type为"internetresult" n_ir 二、 界面中,增加按钮。点击测试post提交。 Blob lblb_args String ls_header String ls_url String ls_args Long ll_length Integer li_rc inet iinet_base,iinet n_ir ir iinet_ba…...

Linux 配置网卡(基础配置、网卡会话配置、网卡绑定配置)

目录 配置网卡基本信息 通过nmcli命令配置网卡 通过配置网卡文件配置网卡 通过nmtui命令配置网卡 通过nm-connection-editor命令配置网卡 网卡高级配置 配置网络会话 配置网卡绑定&#xff08;Bonding&#xff09; 通过nmcli命令配置网卡绑定 nm-connection-editor 进…...

深度学习Week16-yolo.py文件解读(YOLOv5)

目录 简介 需要的基础包和配置 二、主要组件介绍 2.1 parse_model 2.2Detect类 2.3DetectionModel类 三、实验 &#x1f368; 本文为[&#x1f517;365天深度学习训练营]内部限免文章&#xff08;版权归 *K同学啊* 所有&#xff09; &#x1f356; 作者&#xff1a;[K同学啊…...

富文本编辑组件封装,tinymce、tinymce-vue

依赖&#xff1a;package.json yarn add tinymce tinymce/tinymce-vue {"dependencies": {"tinymce/tinymce-vue": "5.0.0","tinymce": "6.3.1","vue": "3.2.45",}, } 本地依赖&#xff1a; 在publ…...

电子作业指导书系统能树立良好的生产形象

“制造”就是以规定的成本、规定的工时、生产出品质均匀、符合规格的产品。从全球新能源汽车的发展来看&#xff0c;其动力电源主要包括锂离子电池、镍氢电池、铅酸电池、超级电容器&#xff0c;其中超级电容器大多以辅助动力源的形式出现。那么&#xff0c;电子作业指导书系统…...

Doris单机部署

文章目录1. 前言2. 安装3. 启动4. 使用1. 前言 Apache Doris 是一款现代 MPP (Massively Parallel Processing大规模并行处理) 的分布式 SQL 分析数据库&#xff0c;所谓分析数据库就是将其数据集分布在许多机器或节点上&#xff0c;以处理大量数据&#xff0c;采用 Apache 2.0…...

利用身份证号获取生日信息

1 问题如何利用Java程序从身份证号中获取生日信息。2 方法采用“截图文字代码”的方式描述。//调用函数获取当前日期以及截取身份证号码中的数字import java.util.Calendar;import java.util.Scanner;public class nain { static Scanner sc new Scanner(System.in); st…...

c++模板的简单认识

文章目录 前言一.泛型编程 函数模板 模板参数的匹配原则 类模板总结前言 ADD函数很好写&#xff0c;但是如果我们要有int类型的&#xff0c;double类型的&#xff0c;char类型的等等各种类型&#xff0c;难道要写这么多不同的ADD函数吗&#xff0c;这么写简直太麻…...

真香!Linux 原来是这么管理内存的

Linux 内存管理模型非常直接明了&#xff0c;因为 Linux 的这种机制使其具有可移植性并且能够在内存管理单元相差不大的机器下实现 Linux&#xff0c;下面我们就来认识一下 Linux 内存管理是如何实现的。 一&#xff0c;基本概念 每个 Linux 进程都会有地址空间&#xff0c;这…...

计网之IP协议和以太网

文章目录一. IP协议1. IPv4报头介绍2. 解决IPv4地址不够用的问题3. IP地址管理4. 路由选择二. 以太网三. 浅谈DNS域名解析系统一. IP协议 IP协议是位于OSI模型中第三层(网络层)的协议, 在这层上工作的不止这一个协议, 但IP协议是网络层传输所使用的最主流的一种协议, 有IPv4和…...

华为OD机试 - 关联子串(Python) | 机试题+算法思路+考点+代码解析 【2023】

关联子串 题目 给定两个字符串str1和str2 如果字符串str1中的字符,经过排列组合后的字符串中 只要有一个是str2的子串 则认为str1是str2的关联子串 若不是关联子串则返回-1 示例一: 输入: str1="abc",str2="efghicaibii" 输出: -1 预制条件: 输入的…...

SpringBoot学习笔记(二)

配置文件分类 SpringBoot中4级配置文件 1级&#xff1a;file&#xff1a;config/application.yaml 【最高】 2级&#xff1a;file&#xff1a;application.yml 3级&#xff1a;classpath&#xff1a;config/application.yml 4级&#xff1a;classpath&#xff1a;application.…...

亚马逊云科技SageMaker:实现自动、可视化管理迭代

现如今&#xff0c;AI正在成为跨时代的技术&#xff0c;在数字经济发展中登上舞台&#xff0c;发挥关键作用。在Gartner发布的《2022年新兴技术成熟度曲线》*报告中&#xff0c;AIGC&#xff08;即AI Generated Content&#xff0c;人工智能自动生成内容&#xff09;被列为2022…...

汽车 Automotive > CAN Transceivers收发器选择

参考&#xff1a;https://www.nxp.com/products/interfaces/can-transceivers/3-3-v-5-v-io-can-transceivers:33VIO-CAN3.3 V / 5V IO CAN收发器组合TJA1042高速CAN收发器&#xff0c;具有待机模式&#xff0c;适用于所有类型的高速CAN网络&#xff0c;在需要低功耗模式的节点…...

AI将如何影响程序员的未来,以及如何不被AI所替代。

随着人工智能技术的不断发展&#xff0c;越来越多的工作被自动化和智能化所取代&#xff0c;其中程序员这个职业也不例外。然而&#xff0c;我们需要客观地分析AI在未来对程序员的影响&#xff0c;并且给出建议&#xff0c;以便程序员能够保持竞争力&#xff0c;不被AI所取代。…...

nginx 常用配置之 pass_proxy

大家好&#xff0c;我是 17。 今天和大家聊聊 pass_proxy 代理。 pass_proxy 代理 在前端代理主要是为了跨域。虽然前端跨域有多种方法&#xff0c;各有利弊&#xff0c;但用代理来跨域对开发是最友好的。用代理可以不用修改产品代码切换线上线下&#xff0c;非常安全。pass…...