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