36

Please find the below code with the chrome capabilities. In fact the browser is not downloading the file to the specified path.

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;
}
Mukesh Takhtani
  • 852
  • 5
  • 15
vini007
  • 595
  • 1
  • 6
  • 13

7 Answers7

45

For Chromedriver try out with:

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);

Note:- Use File.separator to handle slashes, it will put syntax as per os it is executing the code. In windows you need to use \\ for path while if you are using linux or mac then use //

Hope this helps. :)

Shubham Jain
  • 16,610
  • 15
  • 78
  • 125
  • 4
    Or you'll just use File.separator instead of the slashes – Simon Baars Apr 11 '17 at 11:50
  • What if I need to change download path during runtime? I mean set its own path for each test. – Orest Jul 27 '17 at 18:45
  • Or you could use System.IO.Path.Combine which will add the proper separators depending on the OS – victorvartan Dec 10 '18 at 18:24
  • @ShubhamJain When i am trying with headless browser in chrome. I don't see it is working. any clue ? – Guna Yuvan Jul 25 '19 at 13:38
  • 1
    Is there a way to change download path while on **current session**, similar to how you click Chrome Settings->Download ? The answer I saw always incur **building new option + new driver + get a whole new session** . I would wish not to close the current session, since my folder separation based on each item in a drop-down list and there's no need to reload a new page. – Kenny Sep 15 '19 at 22:03
  • Initializing ChromeDriver with Desired capabilities is deprecated. Instead you could just put `options.setExperimentalOption("prefs",chromePrefs); WebDriver driver = new ChromeDriver(options);` – wardaddy Jul 31 '20 at 10:56
  • Please note that you must set the FULL path for it to work, at least for me. Something like `new File("output" + File.separator + "downloads" + File.separator).getAbsolutePath()` – Gabriel Candia Jun 07 '21 at 16:18
21

For Python users who see this page -- here's how I set the download directory in Python Selenium (this is just the Python version of Shubham's accepted answer):

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
Benjamin Loison
  • 3,782
  • 4
  • 16
  • 33
Luke
  • 5,329
  • 2
  • 29
  • 34
  • 3
    I used this as inspiration to my Python code and works well. At the end, it looks like this: 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) – RGregg Aug 29 '19 at 11:43
  • Thank you a lot. This should be the accepted answer (for python). – Philippe Remy Apr 09 '20 at 09:45
  • The os.makedirs command can fail if the target directory already exists, a workaround is: os.makedirs(downloadPath, exist_ok=True) – jsf80238 Jul 25 '20 at 16:04
  • I didn't need the "profile.default_content_settings.popups" line. Just the "download.default_directory" line was sufficient. – David Foster Feb 03 '23 at 15:44
13

2020 Update:

Chrome: v84

ChromeDriver: v83

JDK: OpenJDK 11 (LTS)

Use Paths class for platform-independent file separators.

@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();
}

Output:

output

Doing mvn clean prior to any run also takes care of having to override existing files.

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>
Benjamin Loison
  • 3,782
  • 4
  • 16
  • 33
k_rollo
  • 5,304
  • 16
  • 63
  • 95
  • 2
    an excellent solution and answer. I don't like how you stuck to some exclusively "new" java features - could have done it with something for us corporation zombies who are not allowed to update :) But I want to be clear: You have done me and the community a great service! Thank You! – DraxDomax Dec 10 '20 at 04:54
  • 2
    Java 7 was 10 years ago. It is not "new". The solution to your problem is simple - move on to a company that use something within the last 10 years. You're welcome! – k_rollo Jan 19 '21 at 09:29
  • 1
    ah, sorry, I only looked at the 'prefs' part (as I already have my own system to pipe files into where they need to be) and missed the comment "since java 7"... In some ways, it's better to be the smartest guy in a mediocre group, rather than swimming in deep waters with sharks like you! :D – DraxDomax Jan 19 '21 at 14:44
  • 1
    I admire the honesty. :)) In some ways I also did the same, my skill is closer to developer level (and pretty sure I can be) but I went the less travelled path to get ahead of competition. Now the "rockstar" developers are stuck back in my home country and I was offered a job in Australia. – k_rollo Jan 19 '21 at 22:07
12

The answer which helped me to resolve this issue on 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);
danronmoon
  • 3,814
  • 5
  • 34
  • 56
Darshan Shah
  • 365
  • 4
  • 12
  • A note for those using Windows: the "download.default_directory" string must use backslashes (\\), not regular slashes (/). – user697473 Dec 31 '20 at 21:50
3

For Chrome driver, the below code is worked for me

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);
Bachan Joseph
  • 347
  • 4
  • 5
0

To make it more clean and easy, I developed a library which lets you generate a ChromeOptions object which contains your download folder in one line. For example, to define "/tmp/downloads", use:

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);

The library also contains methods which allow to receive download KPI and perform assertion.

AutomatedOwl
  • 1,039
  • 1
  • 8
  • 14
0

With selenium 4 and Chrome

(Obi Wan Kenobi's "one in a million"):

ChromeOptions chromeOptions = new ChromeOptions();
chromeOptions.setCapability("download.default_directory", "C:\\Users\\me\\Downloads");
driver =new ChromeDriver(chromeOptions);

(failed to work on windows 10 selenium 4, so got this alternate one from this very same thread )

OR

Map<String, Object> prefs = new HashMap<String, Object>();
prefs.put("C:\\Users\\me\\Downloads");
ChromeOptions chromeOptions = new ChromeOptions();
chromeOptions.setExperimentalOption("prefs", prefs);
Benjamin Loison
  • 3,782
  • 4
  • 16
  • 33