1

In my web application which has some automation process to download the files from the website. To achieve that I used selenium c# chrome driver.

Sample code snippets

public void Download(string name,string pass)
{
    try
    {
        ChromeOptions options = new ChromeOptions();
        options.AddArguments("--proxy-server=http://192.168.5.62:8095");
        options.AddUserProfilePreference("safebrowsing.enabled", true);
        options.AddUserProfilePreference("disable-popup-blocking", "true");
        options.AddUserProfilePreference("download.default_directory",@"C:\Temp");

        using (var driver = new ChromeDriver(HostingEnvironment.ApplicationPhysicalPath, options)){

            //driver.findElement(By.xpath("//a/u[contains(text(),'Re-Submit')]")).click();
            driver.FindElementById("save").Click();                               
        }              
    }
    catch (Exception ex)
    {       
        Logger.LogWriter("LAS", ex, "CusDataLogic", "Download");
    }
}

above code (not complete code) works fine and save file properly. But I need to rename that file downloading or after download. Have any possible way to rename that file?

Edited: Please don't mark this as a duplicate. I'm asking for C#, not python. I saw that question too. but it not helped to me

Sachith Wickramaarachchi
  • 5,546
  • 6
  • 39
  • 68

2 Answers2

1

watching directory is not always good, because sometime saved filename is different than filename in URL.

go to chrome download page and loop until all download complete, you can see below how to select special element #shadow-root with CSS selector

using (var driver = new ChromeDriver(HostingEnvironment.ApplicationPhysicalPath, options)))
{
    //driver.findElement(By.xpath("//a/u[contains(text(),'Re-Submit')]")).click();
    driver.FindElementById("save").Click();

    // wait 5 second until download started
    Thread.Sleep(5000);

    // Go to chrome download page
    driver.Navigate().GoToUrl("chrome://downloads/");
    string oldName = "";
    bool downloadcomplete = false;
    string cssNames = "downloads-manager /deep/ downloads-item /deep/ [id='name']";
    string cssDlProgress = "downloads-manager /deep/ downloads-item /deep/ [class*='show-progress']";

    while (!downloadcomplete)
    {
        var progressElements = driver.FindElements(By.CssSelector(cssDlProgress));
        // check until no download progress bar
        if (progressElements.Count() == 0)
        {
            oldName = driver.FindElement(By.CssSelector(cssNames)).Text;
            downloadcomplete = true;
        }
        else
        {
            // download still in progress, wait.
            Thread.Sleep(1000);
        }
    }
    // download complete
    // remove downloaded file
    driver.FindElement(By.CssSelector("downloads-manager /deep/ downloads-item /deep/ [id='remove']")).Click();
    // rename
    File.Move(@"C:\Temp\" + oldName, @"C:\Temp\newname.ext");
}
ewwink
  • 18,382
  • 2
  • 44
  • 54
  • Thanks @ewwink , I have a problem. suppose this download method called inside for loop. each time file download based on parameters until loop false. so each time your logic calls. how to handle that? I need to rename file one by one. and please tell me how to rename file using your code, I'm confused with that – Sachith Wickramaarachchi Nov 26 '18 at 07:36
  • I updated my code. suppose this method called inside `forloop`. based on name and password file will be downloaded. so how to rename each file after download – Sachith Wickramaarachchi Nov 26 '18 at 07:42
  • According to my code files download properly to this path `C:\Temp`. But not showing downloaded file in `chrome://downloads/` menu – Sachith Wickramaarachchi Nov 26 '18 at 07:46
  • oh I forgot that, call it in your Download method and click `id="remove"` to clear download list – ewwink Nov 26 '18 at 07:50
  • for download directory, try https://stackoverflow.com/questions/22536907/ – ewwink Nov 26 '18 at 07:51
  • Can you update your answer and please give me example (to rename the file) – Sachith Wickramaarachchi Nov 26 '18 at 07:54
  • Thank you very much. Can you please explain why download files not appear in `chrome://downloads/` menu? But downloaded to `options.AddUserProfilePreference("download.default_directory",@"C:\Temp");` location. But not appear in `chrome://downloads/` menu – Sachith Wickramaarachchi Nov 26 '18 at 08:18
  • it need `sleep` after clicking `save` element. – ewwink Nov 26 '18 at 08:31
  • I added thread after this line `driver.FindElementById("save").Click();` like this `Thread.Sleep(3000);` But not shownig downloaded files in chrome menu – Sachith Wickramaarachchi Nov 26 '18 at 08:36
  • try increase up to 10 second – ewwink Nov 26 '18 at 08:36
  • I tried your code. But in this line `File.Move(@"C:\Temp\" + oldName, @"C:\Temp\newname.ext");` error occured. `Could not find file 'C:\Temp\'.` reason was `oldName ` not set file name properly. `oldName` value shows as `" "` .I think this line `oldName = driver.FindElement(By.CssSelector(cssNames)).Text;` not working properly – Sachith Wickramaarachchi Nov 26 '18 at 09:15
  • is download started and showing in `chrome://downloads/` ? – ewwink Nov 26 '18 at 09:20
  • In my target website file download start after big process. 3 windows popuped and final window star file download process. downloaded file shows that last popuoped windows's menu. Its ok now, but downloaded file name cant identify in your code – Sachith Wickramaarachchi Nov 26 '18 at 09:23
0

The Snippet Below Will wait Until File downloaded Then return FilePath I Wrote this as an extension method :

public static string GetDonwloadedFileName(this IWebDriver driver)
{
    IJavaScriptExecutor js = (IJavaScriptExecutor)driver;
    js.ExecuteScript("window.open()");
    var allWinowHandles = driver.WindowHandles;
    foreach (var winHandle in allWinowHandles)
    {
        //Switch to second window
        if (!winHandle.Equals(driver.CurrentWindowHandle))
        {
            driver.SwitchTo().Window(winHandle);
        }
    }
    // navigate to chrome downloads
    driver.Navigate().GoToUrl("chrome://downloads");
    IJavaScriptExecutor downloadWindowExecutor = (IJavaScriptExecutor)driver;
    // Wait for Download till 100% completion
    double percentageProgress = (double)0;
    while (percentageProgress != 100)
    {
        try
        {
            percentageProgress = (long)downloadWindowExecutor.ExecuteScript("return document.querySelector('downloads-manager').shadowRoot.querySelector('#downloadsList downloads-item').shadowRoot.querySelector('#progress').value");
            Thread.Sleep(100);
        }
        catch (Exception)
        {
            break;
        }
    }

    string fileTitle = (string)downloadWindowExecutor.ExecuteScript("return document.querySelector('downloads-manager').shadowRoot.querySelector('#downloadsList downloads-item').shadowRoot.querySelector('#show').getAttribute('title')");
    downloadWindowExecutor.ExecuteScript("window.close()");
    return fileTitle;
}

Then You can use file Path to rename it to whatever you need