You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java环境下Selenium Grid文件下载验证问题求助

Selenium Grid(Jenkins部署)中Chrome下载文件的验证方案

问题背景

在Jenkins部署的Selenium Grid上运行Java自动化测试时,Hub节点会将测试请求分配至Node节点执行浏览器操作,但测试代码的文件查找逻辑仅能访问本地文件系统。部分测试需下载并验证文件,此前拦截下载生成文件的Java方法因I-Boss拦截失效,改用chrome://downloads解析文件路径的逻辑在本地运行正常,但在Grid环境中,虽能获取文件名,调用file.exists()却始终找不到文件——原因是下载的文件实际存储在Node节点的文件系统中,本地代码无法直接访问。

核心问题分析

Selenium Grid架构下,测试代码运行在本地或Hub所在机器,而浏览器实例及下载文件均位于Node节点的文件系统内。原有代码通过chrome://downloads提取的路径是Node节点的本地路径,本地Java代码的File API无法跨机器访问该路径,导致文件查找失败。

可行解决方案

方案一:利用Selenium 4+ DevTools API获取文件Base64内容

通过DevTools监听下载事件,直接获取文件的Base64编码内容,无需访问Node节点的文件系统,适配Grid环境:

import org.openqa.selenium.By;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.remote.RemoteWebDriver;
import org.openqa.selenium.devtools.DevTools;
import org.openqa.selenium.devtools.v120.downloads.Downloads;
import java.util.Base64;
import java.net.URL;

public class GridDownloadTest {
    public static void main(String[] args) throws Exception {
        ChromeOptions options = new ChromeOptions();
        // 禁用Chrome安全下载拦截,适配不安全下载场景
        options.addArguments("--safebrowsing-disable-download-protection");
        options.addArguments("--safebrowsing-disable-extension-blacklist");

        // 连接Grid Hub
        RemoteWebDriver driver = new RemoteWebDriver(new URL("http://your-grid-hub:4444/wd/hub"), options);
        ChromeDriver chromeDriver = (ChromeDriver) driver;

        // 初始化DevTools会话
        DevTools devTools = chromeDriver.getDevTools();
        devTools.createSession();

        // 设置下载行为:不保存到Node本地,返回Base64内容
        devTools.send(Downloads.setDownloadBehavior(
                Downloads.SetDownloadBehaviorRequest.newBuilder()
                        .setBehavior("allow")
                        .setDownloadPath("")
                        .build()
        ));

        // 监听下载完成事件,获取文件Base64内容
        devTools.addListener(Downloads.downloadCompleted(), completed -> {
            String downloadId = completed.getDownloadId();
            try {
                Downloads.GetDownloadResponse response = devTools.send(Downloads.getDownload(downloadId));
                String fileBase64 = response.getContent();
                // 将Base64转为字节数组,用于后续验证
                byte[] fileBytes = Base64.getDecoder().decode(fileBase64);
                
                // 此处添加文件内容验证逻辑,比如检查文件哈希、内容格式等
                System.out.println("文件已获取,大小:" + fileBytes.length + "字节");
            } catch (Exception e) {
                e.printStackTrace();
            }
        });

        // 触发下载操作(示例,替换为实际下载元素定位)
        driver.findElement(By.id("download-trigger")).click();

        // 等待下载完成(可配合显式等待或自定义超时逻辑)
        Thread.sleep(10000);

        driver.quit();
    }
}

方案二:通过Node节点HTTP服务获取文件

在固定的Grid Node节点上部署简易HTTP服务,暴露下载目录,测试代码通过HTTP请求拉取文件:

  1. 在Node节点的Chrome下载目录(如/var/lib/jenkins/chrome-downloads)启动HTTP服务:
    python3 -m http.server 8000 --directory /var/lib/jenkins/chrome-downloads
    
  2. 测试代码中获取Node节点IP并下载文件:
    import org.openqa.selenium.remote.RemoteWebDriver;
    import java.net.URI;
    import java.net.http.HttpClient;
    import java.net.http.HttpRequest;
    import java.net.http.HttpResponse;
    import java.io.FileOutputStream;
    
    // 获取当前Node节点IP
    String nodeHost = (String) ((RemoteWebDriver)driver).getCapabilities().getCapability("se:host");
    String downloadUrl = "http://" + nodeHost + ":8000/your-download-file.pdf";
    
    // 下载文件到本地临时目录
    HttpClient client = HttpClient.newHttpClient();
    HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create(downloadUrl))
            .build();
    HttpResponse<byte[]> response = client.send(request, HttpResponse.BodyHandlers.ofByteArray());
    
    // 将字节数组写入本地文件,用于验证
    try (FileOutputStream fos = new FileOutputStream("/tmp/local-download.pdf")) {
        fos.write(response.body());
    }
    
    // 后续文件验证逻辑
    

方案三:挂载共享存储统一下载目录

将所有Node节点的Chrome下载目录挂载至同一共享存储(如NFS、Jenkins共享工作空间),测试代码直接访问共享存储中的文件:

  1. 配置ChromeOptions指定共享目录为下载路径:
    ChromeOptions options = new ChromeOptions();
    options.setExperimentalOption("prefs", Map.of(
            "download.default_directory", "/shared-grid-downloads",
            "download.prompt_for_download", false
    ));
    
  2. 确保测试代码运行机器可访问该共享目录,之后即可用原有File API直接操作文件。

原有代码的局限性说明

原有通过chrome://downloads解析路径的逻辑仅适用于本地运行场景,在Grid环境中,解析得到的是Node节点的本地路径,本地代码无法跨机器访问。建议优先采用方案一(DevTools API),无需依赖Node节点的配置变更,适配性更强。

内容的提问来源于stack exchange,提问作者Tony

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.11 13:05:05