如何在 selenium Chrome 功能中设置默认下载目录?

Posted

技术标签:

【中文标题】如何在 selenium Chrome 功能中设置默认下载目录?【英文标题】:How to set default download directory in selenium Chrome Capabilities? 【发布时间】:2016-04-03 14:09:41 【问题描述】:

请找到以下具有 chrome 功能的代码。实际上浏览器并没有将文件下载到指定路径。

private static DesiredCapabilities getChromeCapabilities() throws Exception 

    String chromePath = BrowserUtil.class.getResource("/Browserdrivers/chromedriver.exe").getPath();
    System.setProperty("webdriver.chrome.driver", chromePath);
    String downloadFilepath = "C:\\TestDownloads";
    ChromeOptions options = new ChromeOptions();
    HashMap<String, Object> chromePrefs = new HashMap<String, Object>();
    chromePrefs.put("profile.default_content_settings.popups", 0);
    chromePrefs.put("download.default_directory", downloadFilepath);
    options.setExperimentalOption("prefs", chromePrefs);
    options.addArguments("--test-type");
    options.addArguments("start-maximized", "disable-popup-blocking");

    DesiredCapabilities chromeCapabilities = DesiredCapabilities.chrome();
    setProxy(chromeCapabilities);
    chromeCapabilities.setPlatform(Platform.WINDOWS);
    chromeCapabilities.setCapability("name", MDC.get("testname"));
    chromeCapabilities.setCapability(ChromeOptions.CAPABILITY, options);
    return chromeCapabilities;

【问题讨论】:

【参考方案1】:

对于 Chromedriver 试用:

String downloadFilepath = "/path/to/download";
HashMap<String, Object> chromePrefs = new HashMap<String, Object>();
chromePrefs.put("profile.default_content_settings.popups", 0);
chromePrefs.put("download.default_directory", downloadFilepath);
ChromeOptions options = new ChromeOptions();
options.setExperimentalOption("prefs", chromePrefs);
DesiredCapabilities cap = DesiredCapabilities.chrome();
cap.setCapability(CapabilityType.ACCEPT_SSL_CERTS, true);
cap.setCapability(ChromeOptions.CAPABILITY, options);
WebDriver driver = new ChromeDriver(cap);

注意:- 在 windows 中,您需要使用 \\ 作为路径,而如果您使用的是 linux 或 mac,则使用 //

希望这会有所帮助。 :)

【讨论】:

或者您将只使用 File.separator 而不是斜杠 如果我需要在运行时更改下载路径怎么办?我的意思是为每个测试设置自己的路径。 或者您可以使用 System.IO.Path.Combine 它将根据操作系统添加适当的分隔符 @ShubhamJain 当我在 chrome 中尝试使用无头浏览器时。我没有看到它正在工作。有什么线索吗? 有没有办法在 当前会话 上更改下载路径,类似于单击 Chrome 设置->下载的方式?我看到的答案总是导致 build new option + new driver + get a whole new session 。我不希望关闭当前会话,因为我的文件夹分隔基于下拉列表中的每个项目,并且无需重新加载新页面。【参考方案2】:

帮助我在 Windows 上解决此问题的答案:(https://bugs.chromium.org/p/chromedriver/issues/detail?id=783)。

Map<String, Object> prefs = new HashMap<String, Object>();
prefs.put("download.default_directory",  System.getProperty("user.dir")+ File.separator + "externalFiles" + File.separator + "downloadFiles");
ChromeOptions options = new ChromeOptions();
options.setExperimentalOption("prefs", prefs);
ChromeDriver driver = new ChromeDriver(options);

【讨论】:

使用 Windows 的注意事项:“download.default_directory”字符串必须使用反斜杠 (\),而不是正斜杠 (/)。【参考方案3】:

为了让它更干净和简单,我开发了一个library,它可以让你生成一个 ChromeOptions 对象,其中包含你的下载文件夹。例如,要定义“/tmp/downloads”,请使用:

private SeleniumDownloadKPI seleniumDownloadKPI;

@BeforeEach
void setUpTest() 

    // New instance of SeleniumDownloadKPI with given download folder.
    seleniumDownloadKPI =
         new SeleniumDownloadKPI("/tmp/downloads");
    ChromeOptions chromeOptions =
            seleniumDownloadKPI.generateDownloadFolderCapability();
    driver = new ChromeDriver(chromeOptions);

library 还包含允许接收下载 KPI 并执行断言的方法。

【讨论】:

【参考方案4】:

对于 Chrome 驱动程序,以下代码适用于我

String downloadFilepath = "/path/to/download";
HashMap<String, Object> chromePrefs = new HashMap<String, Object>();
chromePrefs.put("profile.default_content_settings.popups", 0);
chromePrefs.put("download.default_directory", downloadFilepath);
ChromeOptions options = new ChromeOptions();
options.setExperimentalOption("prefs", chromePrefs);
WebDriver driver = new ChromeDriver(options);

【讨论】:

【参考方案5】:

对于看到此页面的 Python 用户——这是我在 Python Selenium 中设置下载目录的方式(这只是 Shubham 接受的答案的 Python 版本):

def newChromeBrowser(headless=True, downloadPath=None):
    """ Helper function that creates a new Selenium browser """
    options = webdriver.ChromeOptions()
    if headless:
        options.add_argument('headless')
    if downloadPath is not None:
        prefs = 
        os.makedirs(downloadPath)
        prefs["profile.default_content_settings.popups"]=0
        prefs["download.default_directory"]=downloadPath
        options.add_experimental_option("prefs", prefs)
    browser = webdriver.Chrome(options=options, executable_path=CHROMEDRIVER_PATH)
    return browser

【讨论】:

我将此作为我 Python 代码的灵感来源,并且运行良好。最后,它看起来像这样: path_dest = '//path/to/download/' prefs = prefs['profile.default_content_settings.popups']=0 prefs['download.default_directory']=path_dest options = Options () options.add_experimental_option('prefs',prefs) 非常感谢。这应该是公认的答案(对于 python)。 如果目标目录已经存在,os.makedirs 命令会失败,解决方法是:os.makedirs(downloadPath, exist_ok=True)【参考方案6】:

2020 年更新:

Chrome:v84

Chrome 驱动程序:v83

JDK:OpenJDK 11 (LTS)

使用Paths 类作为独立于平台的文件分隔符。

@Test
public void doFileDownload() throws Throwable 
    // Since Java 7: Relative path from project root dir
    // Put in target dir to avoid committing downloaded files
    var downloadDir = Paths.get("target").toAbsolutePath().toString();

    var prefs = new HashMap<String, Object>();
    prefs.put("download.default_directory", downloadDir); // Bypass default download directory in Chrome
    prefs.put("safebrowsing.enabled", "false"); // Bypass warning message, keep file anyway (for .exe, .jar, etc.)
    var opts = new ChromeOptions();
    opts.setHeadless(true);
    opts.setExperimentalOption("prefs", prefs);

    var driver = new ChromeDriver(opts); // ChromeDriver binary is added to PATH env var
    driver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);
    driver.manage().window().maximize();
    driver.get("https://the-internet.herokuapp.com/download");

    var downloadLink = driver.findElement(By.cssSelector("a[href*='some-file.txt']"));
    var downloadHref = downloadLink.getAttribute("href").replace(":", "");
    var downloadFileName = Paths.get(downloadHref).getFileName().toString();
    downloadLink.click();

    // Wait download to finish for 60s
    var downloadFilePath = Paths.get(downloadDir, downloadFileName);
    new WebDriverWait(driver, 60).until(d -> downloadFilePath.toFile().exists());

    // Since Java 11: Read content of downloaded file
    var content = Files.readString(downloadFilePath);

    // Do tests with string content...
    log.info("Content=", content);

    driver.quit();

输出:

在任何运行之前执行mvn clean 还需要注意必须覆盖现有文件。

pom.xml:

<properties>
    <!-- Remove encoding warnings -->
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>

<dependencies>
    <!-- https://mvnrepository.com/artifact/org.seleniumhq.selenium/selenium-server -->
    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-server</artifactId>
        <version>3.141.59</version>
        <scope>test</scope>
    </dependency>
    <!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter -->
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter</artifactId>
        <version>5.6.2</version>
        <scope>test</scope>
    </dependency>
</dependencies>

<build>
    <plugins>
        <!-- https://mvnrepository.com/artifact/org.apache.maven.plugins/maven-compiler-plugin -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.8.1</version>
            <configuration>
                <release>11</release>
            </configuration>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.22.2</version>
        </plugin>
    </plugins>
</build>

【讨论】:

一个很好的解决方案和答案。我不喜欢你如何坚持一些专门的“新”java特性——本可以为我们那些不允许更新的公司僵尸做一些事情:)但我想明确一点:你给我和社区做了一个很棒的服务!谢谢! Java 7 是 10 年前的事了。它不是“新的”。解决您的问题的方法很简单 - 转到一家在过去 10 年内使用过某些东西的公司。不客气! 啊,抱歉,我只查看了“首选项”部分(因为我已经有自己的系统将文件传送到需要的位置)并错过了“自 java 7 以来”的评论。 ……在某些方面,做一个平庸的群体中最聪明的人,还不如和你这样的鲨鱼一起在深水里游泳! :D 我很欣赏这种诚实。 :)) 在某些方面我也做了同样的事情,我的技能更接近开发人员的水平(我很确定我可以做到),但我走的是人迹罕至的道路以在竞争中领先。现在,“摇滚明星”开发人员被困在我的祖国,而我在澳大利亚得到了一份工作。

以上是关于如何在 selenium Chrome 功能中设置默认下载目录?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Google Chrome 的内联 Javascript 中设置断点?

如何在 Selenium Chromedriver 中设置时区?

使用 Gulp 时如何在 IDEA 中设置 Chrome 识别的断点?

如何在 Selenium WebDriver 中设置浏览器宽度和高度?

如何在 chrome 扩展 manifest.json 文件中设置多个内容安全策略

如何在 Google Chrome DevTools 的 lambda 调用中设置断点?