Azure Pipeline中Selenium测试无法获取下载文件问题
解决Azure Pipeline中Selenium下载PDF后找不到文件的问题
我来帮你排查这个问题——你遇到的FileNotFoundException是因为在Azure Pipeline的Ubuntu虚拟机环境里,PDF文件要么没被正确下载到指定路径,要么路径本身存在权限或不存在的问题。下面是具体的排查和解决步骤:
1. 先确保目标下载目录存在且有权限
Windows本地的项目目录结构是现成的,但Azure Pipeline的Ubuntu Agent是临时构建环境,src/test/resources目录可能还没创建,或者Agent用户没有写入权限。
解决方案:
- 在测试代码里先检查并创建目录:
String downloadDirPath = System.getProperty("user.dir") + File.separator + "src" + File.separator + "test" + File.separator + "resources"; File downloadDir = new File(downloadDirPath); // 递归创建多级目录,避免单个目录不存在的情况 if (!downloadDir.exists()) { downloadDir.mkdirs(); } // 再把路径设置到Chrome偏好里 prefs.put("download.default_directory", downloadDirPath);
- 或者在Pipeline的Gradle任务前,先通过Bash命令创建目录(双重保险):
修改你的yml文件:
jobs: - job: Test Running timeoutInMinutes: 180 pool: vmImage: ubuntu-20.04 continueOnError: true steps: - bash: mkdir -p src/test/resources displayName: Create download directory - task: Gradle@2 displayName: Run Tests against UK Region inputs: gradleWrapperFile: gradlew tasks: test
2. 配置无头Chrome的下载参数(关键)
Azure Pipeline里运行Selenium通常是用无头模式的Chrome,而无头模式默认的下载行为和正常模式不一样,必须额外配置才能让文件下载到指定目录。
更新你的Selenium ChromeOptions配置:
Map<String, Object> prefs = new HashMap<String, Object>(); prefs.put("googlegeolocationaccess.enabled", false); prefs.put("profile.default_content_setting_values.geolocation", 2); prefs.put("profile.default_content_setting_values.notifications", 1); prefs.put("profile.managed_default_content_settings", 1); // 处理下载目录 String downloadDirPath = System.getProperty("user.dir") + File.separator + "src" + File.separator + "test" + File.separator + "resources"; File downloadDir = new File(downloadDirPath); if (!downloadDir.exists()) { downloadDir.mkdirs(); } prefs.put("download.default_directory", downloadDirPath); // 新增无头模式下载的关键配置 prefs.put("download.prompt_for_download", false); // 禁止下载弹窗 prefs.put("download.directory_upgrade", true); // 允许替换旧的下载目录 prefs.put("plugins.always_open_pdf_externally", true); // 让Chrome直接下载PDF,而不是在浏览器里打开 ChromeOptions chromeOptions = new ChromeOptions(); chromeOptions.setExperimentalOption("prefs", prefs); // 添加Ubuntu环境下必须的无头模式参数 chromeOptions.addArguments("--headless=new"); chromeOptions.addArguments("--disable-gpu"); chromeOptions.addArguments("--no-sandbox"); // Ubuntu环境下必须禁用沙箱,否则Chrome启动失败 chromeOptions.addArguments("--disable-dev-shm-usage"); // 解决Ubuntu虚拟机内存不足的问题
3. 等待文件下载完成再读取
Windows本地下载速度快,文件瞬间就存在,但Pipeline的虚拟机可能因为网络或性能问题,下载有延迟——你的代码可能在文件还没下载完就去读取,自然会找不到。
添加等待逻辑:
// 假设你要读取的PDF文件名是MyPdf.pdf File pdfFile = new File(downloadDirPath + File.separator + "MyPdf.pdf"); int waitSeconds = 0; int maxWait = 30; // 最多等30秒 while (!pdfFile.exists() && waitSeconds < maxWait) { try { Thread.sleep(1000); // 每秒检查一次 waitSeconds++; } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } if (pdfFile.exists()) { // 正常读取PDF PDDocument document = PDDocument.load(pdfFile); // 后续业务逻辑 } else { throw new FileNotFoundException("PDF下载超时,未找到文件:" + pdfFile.getAbsolutePath()); }
4. 检查路径大小写问题
Ubuntu是大小写敏感的文件系统,Windows则不是。比如如果实际下载的文件名是mypdf.pdf,但你代码里写的是MyPdf.pdf,就会找不到文件。
验证方法:在Pipeline里加个步骤,打印下载目录的内容,确认文件是否存在以及文件名是否正确:
steps: - bash: ls -la src/test/resources/ displayName: Check download directory content condition: always() # 即使测试失败也要执行这个步骤,方便排查
总结
按照上面的步骤依次排查,重点是确保目录存在、配置无头Chrome的下载参数、添加下载等待逻辑——这三个点是解决Azure Pipeline中Selenium下载文件问题的核心方案。
内容的提问来源于stack exchange,提问作者SeleniumUser
相关产品推荐
相关产品推荐

