Java实现url页面截图功能~目前实现了windows、linux(centos7)版本,谷歌浏览器需要下载90.x版本,目前暂时没找到安装包
代码
package com.ruoyi.school.util;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Base64;public class ChromeScreenshotUtil {private static final String CHROME_PATH = "C:/Program Files/Google/Chrome/Application/chrome.exe";private static final String TEMP_SCREENSHOT_DIR = "D:/project/uploadFile";static {// 初始化检查File chromeFile = new File(CHROME_PATH);if (!chromeFile.exists()) {throw new RuntimeException("Chrome未找到:" + CHROME_PATH);}File dir = new File(TEMP_SCREENSHOT_DIR);if (!dir.exists() && !dir.mkdirs()) {throw new RuntimeException("无法创建临时目录:" + TEMP_SCREENSHOT_DIR);}}public String captureScreenshotAsBase64(String url) throws IOException, InterruptedException {return captureScreenshotAsBase64(url, 1200, 2000, 10000);}public String captureScreenshotAsBase64(String url, int width, int height, int delay) throws IOException, InterruptedException {String fileName = "temp_screenshot_" + System.currentTimeMillis() + ".png";File tempFile = new File(TEMP_SCREENSHOT_DIR, fileName);String outputPath = tempFile.getAbsolutePath();try {// 执行Chrome截图(省略,同之前)ProcessBuilder processBuilder = new ProcessBuilder(CHROME_PATH,"--headless","--disable-gpu","--no-sandbox","--window-size=" + width + "," + height,"--virtual-time-budget=" + delay,"--screenshot=" + outputPath,url);processBuilder.directory(new File(CHROME_PATH).getParentFile());Process process = processBuilder.start();captureStream(process.getInputStream(), "输出");captureStream(process.getErrorStream(), "错误");int exitCode = process.waitFor(60, java.util.concurrent.TimeUnit.SECONDS) ? process.exitValue() : -1;if (exitCode != 0) {throw new RuntimeException("Chrome退出码:" + exitCode);}// 等待文件生成int retryCount = 0;while (retryCount < 5) {if (tempFile.exists() && tempFile.length() > 0) {Thread.sleep(2000);break;}Thread.sleep(1000);retryCount++;}if (retryCount >= 5 || !tempFile.exists() || tempFile.length() == 0) {throw new RuntimeException("图片未生成:" + outputPath);}// 关键:读取字节并验证byte[] imageBytes = readFileToBytes(tempFile);// 验证PNG头(前8字节必须为89 50 4E 47 0D 0A 1A 0A)if (imageBytes.length < 8) {throw new RuntimeException("字节数组过短,不是有效的PNG");}byte[] pngHeader = new byte[]{(byte)0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A};for (int i = 0; i < 8; i++) {if (imageBytes[i] != pngHeader[i]) {throw new RuntimeException("PNG头验证失败,第" + i + "字节应为" + String.format("%02X", pngHeader[i]) + ",实际为" + String.format("%02X", imageBytes[i]));}}// 生成Base64String base64Str = Base64.getEncoder().encodeToString(imageBytes);String result = "data:image/png;base64," + base64Str;return result;} finally {// 保留文件用于手动验证tempFile.delete();}}// 循环读取字节,确保完整private byte[] readFileToBytes(File file) throws IOException {if (!file.exists()) {throw new FileNotFoundException("文件不存在:" + file.getAbsolutePath());}if (file.length() == 0) {throw new IOException("文件为空");}try (InputStream is = new FileInputStream(file);ByteArrayOutputStream bos = new ByteArrayOutputStream()) {byte[] buffer = new byte[4096];int bytesRead;while ((bytesRead = is.read(buffer)) != -1) {bos.write(buffer, 0, bytesRead);}bos.flush();byte[] result = bos.toByteArray();if (result.length != file.length()) {throw new IOException("读取不完整:文件大小=" + file.length() + ",读取大小=" + result.length);}return result;}}private void captureStream(InputStream is, String type) {new Thread(() -> {try (BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {String line;while ((line = br.readLine()) != null) {System.out.println("[Chrome" + type + "] " + line);}} catch (IOException e) {e.printStackTrace();}}).start();}public static void main(String[] args) {try {String url = "http://192.168.110.175:8083/#/";String base64 = new ChromeScreenshotUtil().captureScreenshotAsBase64(url);System.out.println(base64);} catch (Exception e) {e.printStackTrace();}}
}