Selenium give file name when downloading Selenium give file name when downloading python python

Selenium give file name when downloading


Here is another simple solution, where you can wait until the download completed and then get the downloaded file name from chrome downloads.

Chrome:

# method to get the downloaded file namedef getDownLoadedFileName(waitTime):    driver.execute_script("window.open()")    # switch to new tab    driver.switch_to.window(driver.window_handles[-1])    # navigate to chrome downloads    driver.get('chrome://downloads')    # define the endTime    endTime = time.time()+waitTime    while True:        try:            # get downloaded percentage            downloadPercentage = driver.execute_script(                "return document.querySelector('downloads-manager').shadowRoot.querySelector('#downloadsList downloads-item').shadowRoot.querySelector('#progress').value")            # check if downloadPercentage is 100 (otherwise the script will keep waiting)            if downloadPercentage == 100:                # return the file name once the download is completed                return driver.execute_script("return document.querySelector('downloads-manager').shadowRoot.querySelector('#downloadsList downloads-item').shadowRoot.querySelector('div#content  #file-link').text")        except:            pass        time.sleep(1)        if time.time() > endTime:            break

Firefox:

def getDownLoadedFileName(waitTime):    driver.execute_script("window.open()")    WebDriverWait(driver,10).until(EC.new_window_is_opened)    driver.switch_to.window(driver.window_handles[-1])    driver.get("about:downloads")    endTime = time.time()+waitTime    while True:        try:            fileName = driver.execute_script("return document.querySelector('#contentAreaDownloadsView .downloadMainArea .downloadContainer description:nth-of-type(1)').value")            if fileName:                return fileName        except:            pass        time.sleep(1)        if time.time() > endTime:            break

Once you click on the download link/button, just call the above method.

 # click on download link browser.find_element_by_partial_link_text("Excel").click() # get the downloaded file name latestDownloadedFileName = getDownLoadedFileName(180) #waiting 3 minutes to complete the download print(latestDownloadedFileName) 

JAVA + Chrome:

Here is the method in java.

public String waitUntilDonwloadCompleted(WebDriver driver) throws InterruptedException {      // Store the current window handle      String mainWindow = driver.getWindowHandle();            // open a new tab      JavascriptExecutor js = (JavascriptExecutor)driver;      js.executeScript("window.open()");     // switch to new tab    // Switch to new window opened      for(String winHandle : driver.getWindowHandles()){          driver.switchTo().window(winHandle);      }     // navigate to chrome downloads      driver.get("chrome://downloads");            JavascriptExecutor js1 = (JavascriptExecutor)driver;      // wait until the file is downloaded      Long percentage = (long) 0;      while ( percentage!= 100) {          try {              percentage = (Long) js1.executeScript("return document.querySelector('downloads-manager').shadowRoot.querySelector('#downloadsList downloads-item').shadowRoot.querySelector('#progress').value");              //System.out.println(percentage);          }catch (Exception e) {            // Nothing to do just wait        }          Thread.sleep(1000);      }     // get the latest downloaded file name      String fileName = (String) js1.executeScript("return document.querySelector('downloads-manager').shadowRoot.querySelector('#downloadsList downloads-item').shadowRoot.querySelector('div#content #file-link').text");     // get the latest downloaded file url      String sourceURL = (String) js1.executeScript("return document.querySelector('downloads-manager').shadowRoot.querySelector('#downloadsList downloads-item').shadowRoot.querySelector('div#content #file-link').href");      // file downloaded location      String donwloadedAt = (String) js1.executeScript("return document.querySelector('downloads-manager').shadowRoot.querySelector('#downloadsList downloads-item').shadowRoot.querySelector('div.is-active.focus-row-active #file-icon-wrapper img').src");      System.out.println("Download deatils");      System.out.println("File Name :-" + fileName);      System.out.println("Donwloaded path :- " + donwloadedAt);      System.out.println("Downloaded from url :- " + sourceURL);     // print the details      System.out.println(fileName);      System.out.println(sourceURL);     // close the downloads tab2      driver.close();     // switch back to main window      driver.switchTo().window(mainWindow);      return fileName;  }

This is how to call this in your java script.

// download triggering step downloadExe.click();// now waituntil download finish and then get file nameSystem.out.println(waitUntilDonwloadCompleted(driver));

Output:

Download deatils

File Name :-RubyMine-2019.1.2 (7).exe

Donwloaded path :- chrome://fileicon/C%3A%5CUsers%5Csupputuri%5CDownloads%5CRubyMine-2019.1.2%20(7).exe?scale=1.25x

Downloaded from url :- https://download-cf.jetbrains.com/ruby/RubyMine-2019.1.2.exe

RubyMine-2019.1.2 (7).exe


You cannot specify name of download file through selenium. However, you can download the file, find the latest file in the downloaded folder, and rename as you want.

Note: borrowed methods from google searches may have errors. but you get the idea.

import osimport shutilfilename = max([Initial_path + "\\" + f for f in os.listdir(Initial_path)],key=os.path.getctime)shutil.move(filename,os.path.join(Initial_path,r"newfilename.ext"))


Hope this snippet is not that confusing. It took me a while to create this and is really useful, because there has not been a clear answer to this problem, with just this library.

import osimport timedef tiny_file_rename(newname, folder_of_download):    filename = max([f for f in os.listdir(folder_of_download)], key=lambda xa :   os.path.getctime(os.path.join(folder_of_download,xa)))    if '.part' in filename:        time.sleep(1)        os.rename(os.path.join(folder_of_download, filename), os.path.join(folder_of_download, newname))    else:        os.rename(os.path.join(folder_of_download, filename),os.path.join(folder_of_download,newname))

Hope this saves someone's day, cheers.

EDIT: Thanks to @Om Prakash editing my code, it made me remember that I didn't explain the code thoughly.

Using the max([]) function could lead to a race condition, leaving you with empty or corrupted file(I know it from experience). You want to check if the file is completely downloaded in the first place. This is due to the fact that selenium don't wait for the file download to complete, so when you check for the last created file, an incomplete file will show up on your generated list and it will try to move that file. And even then, you are better off waiting a little bit for the file to be free from Firefox.

EDIT 2: More Code

I was asked if 1 second was enough time and mostly it is, but in case you need to wait more than that you could change the above code to this:

import osimport timedef tiny_file_rename(newname, folder_of_download, time_to_wait=60):    time_counter = 0    filename = max([f for f in os.listdir(folder_of_download)], key=lambda xa :   os.path.getctime(os.path.join(folder_of_download,xa)))    while '.part' in filename:        time.sleep(1)        time_counter += 1        if time_counter > time_to_wait:            raise Exception('Waited too long for file to download')    filename = max([f for f in os.listdir(folder_of_download)], key=lambda xa :   os.path.getctime(os.path.join(folder_of_download,xa)))    os.rename(os.path.join(folder_of_download, filename), os.path.join(folder_of_download, newname))