12

I am new to selenium and i would like to download file with selenium chrome web driver in specific custom folder. In default the file is downloading in browser specified download path. Any one suggest the best solution for downloading file in custom path in C# Selenium.

Sharathi RB
  • 867
  • 2
  • 9
  • 24

2 Answers2

18

Hope it will be help for you!!

var chromeOptions = new ChromeOptions();
 chromeOptions.AddUserProfilePreference("download.default_directory", "Your_Path");
 chromeOptions.AddUserProfilePreference("intl.accept_languages", "nl");
 chromeOptions.AddUserProfilePreference("disable-popup-blocking", "true");
var driver = new ChromeDriver("Driver_Path", chromeOptions);
JKK
  • 218
  • 1
  • 3
  • 7
  • 1
    How to get the name of file downloaded? or change the default directory after WebDriver started? – Rodrigo Vieira Dec 21 '20 at 17:26
  • @Slowaways I have not tried it yet, but my guess is you chose a temp folder on startup and after each download you can enumerate the directory to find out the name and (re)move the file to prepare for the next download. – wischi Feb 13 '21 at 17:39
1

You need to hack a bit so you can download the file at a specified location. Option 1: Use a third-party tool like AutoIt which can interact with the Windows pop-up and you can specify the path using it. Option 2: Write a custom method that can do the download using the API.

                    var downloadDocLink = webDriver.FindElement(By.XPath("{}")).GetAttribute("onclick");
                    string toBeSearched = "{string}"; //this string needs to be trimmed from the url
                    string downloadUrl = downloadDocLink.Substring(downloadDocLink.IndexOf(toBeSearched) + toBeSearched.Length);
                    var data = webDriver.DownloadByApiCall(downloadUrl);
                    var fileName = webDriver.FindElement(By.XPath("{Xpath}")).Text;

                    //Save result of report api call to file
                    var val = ConfigurationManager.AppSettings["OutputPath"];
                    var path = Environment.ExpandEnvironmentVariables(val);
                    var filePath = Path.Combine(path, fileName);

                    var dir = Path.GetDirectoryName(path);
                    Console.WriteLine($"Saving file with {data.Length} bytes to {path}.");
                    if (!Directory.Exists(dir))
                        Directory.CreateDirectory(dir);
                    File.WriteAllBytes(filePath, data);

                    //Ensure file was downloaded          
                    var exists = webDriver.FileExistsSpinWait(filePath);
                    Assert.IsTrue(exists, $"The downloaded report is not present in the download folder: \n{filePath}");

                    //Remove file and ensure deleted
                    File.Delete(filePath);
                    Assert.IsFalse(File.Exists(filePath));

Helper method to download by API call

public static byte[] DownloadByApiCall(this IWebDriver driver, string apiCall)
        {
            var uri = new Uri(driver.Url);            
            var path = $"{url}/{apiCall}";

            byte[] data = null;
            try
            {
                var webRequest = (HttpWebRequest)WebRequest.Create(path);

                webRequest.CookieContainer = new CookieContainer();
                foreach (var cookie in driver.Manage().Cookies.AllCookies)
                    webRequest.CookieContainer.Add(new System.Net.Cookie(cookie.Name, cookie.Value, cookie.Path, string.IsNullOrWhiteSpace(cookie.Domain) ? uri.Host : cookie.Domain));

                var webResponse = (HttpWebResponse)webRequest.GetResponse();
                var ms = new MemoryStream();
                var responseStream = webResponse.GetResponseStream();
                responseStream.CopyTo(ms);
                data = ms.ToArray();
                responseStream.Close();
                webResponse.Close();
            }
            catch (WebException webex)
            {
                var errResp = webex.Response;
                using (var respStream = errResp.GetResponseStream())
                {
                    var reader = new StreamReader(respStream);
                    Assert.Fail($"Error getting file from the server({webex.Status} - {webex.Message}): {reader.ReadToEnd()}.");
                }
            }

            return data;
        }

This works for me, it asserts if the download was successful and it's rerunnable as well as we're deleting the file in the end. Hope this helps!

Vish
  • 81
  • 8