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

如何使用Selenium(Java)实现Vaadin Upload文件上传?

Vaadin Upload 组件的 Selenium Java 文件上传方案

Vaadin Upload 不生成传统的 <input type="file"> 元素,直接向 target URL 发 POST 请求失败的核心原因是请求未携带浏览器会话的认证信息(如 Cookie、CSRF Token),服务器会拒绝无会话的上传请求。以下是可行的实现方案:

核心思路

利用 Selenium 的 JavascriptExecutor 在浏览器上下文内发送上传请求,自动复用当前浏览器的会话 Cookie 和 Vaadin 所需的请求头,避免会话不一致问题。

具体代码实现

import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.By;

public class VaadinUploadHandler {
    public static void uploadFile(WebDriver driver, String filePath) {
        // 定位 Vaadin Upload 组件
        WebElement uploadElement = driver.findElement(By.tagName("vaadin-upload"));
        String targetUrl = uploadElement.getAttribute("target");
        
        // 构造 JavaScript 代码,在浏览器内发送上传请求
        String jsScript = String.format("""
            return new Promise((resolve, reject) => {
                const fileInput = document.createElement('input');
                fileInput.type = 'file';
                fileInput.style.display = 'none';
                fileInput.onchange = function() {
                    const file = this.files[0];
                    const formData = new FormData();
                    formData.append('file', file);
                    
                    const xhr = new XMLHttpRequest();
                    xhr.open('POST', '%s', true);
                    xhr.onload = function() {
                        if (xhr.status >= 200 && xhr.status < 300) {
                            resolve(xhr.responseText);
                        } else {
                            reject(new Error('Upload failed with status: ' + xhr.status));
                        }
                    };
                    xhr.onerror = function() {
                        reject(new Error('Network error during upload'));
                    };
                    xhr.send(formData);
                };
                document.body.appendChild(fileInput);
                fileInput.dispatchEvent(new MouseEvent('click'));
                arguments[0].sendKeys('%s');
                document.body.removeChild(fileInput);
            });
        """, targetUrl, filePath);
        
        try {
            // 执行 JS 并等待上传完成
            ((JavascriptExecutor) driver).executeAsyncScript(jsScript, uploadElement);
            System.out.println("文件上传成功");
        } catch (Exception e) {
            System.err.println("文件上传失败: " + e.getMessage());
        }
    }
}

关键细节说明

  • 会话复用:通过浏览器内的 XMLHttpRequest 发送请求,自动携带当前会话的 Cookie(如 JSESSIONID)和 Vaadin 内部的 CSRF 令牌,避免服务器认证拦截。
  • FormData 格式:Vaadin Upload 期望接收 multipart/form-data 格式的请求,通过 FormData 构造符合要求的表单数据。
  • 异步执行:使用 executeAsyncScript 等待上传请求完成,确保 Selenium 不会提前执行后续操作。

替代方案(针对 Vaadin 14+)

如果上述方法仍有问题,可以尝试直接触发 Vaadin Upload 组件内部的上传逻辑:

WebElement uploadElement = driver.findElement(By.tagName("vaadin-upload"));
// 定位组件 Shadow DOM 内的 input 元素
WebElement internalInput = (WebElement) ((JavascriptExecutor) driver).executeScript("""
    const upload = arguments[0];
    const input = upload.shadowRoot.querySelector('input[type="file"]');
    input.style.display = 'block';
    return input;
""", uploadElement);
// 执行传统的文件上传操作
internalInput.sendKeys(filePath);

注:Vaadin 组件使用 Shadow DOM,需通过 shadowRoot 定位内部的 input 元素。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 16:12:40