在 selenium webdriver JAVA 中等待下载完成

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/22714112/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-13 17:26:51  来源:igfitidea点击:

Wait for Download to finish in selenium webdriver JAVA

javaselenium-webdriver

提问by qaepk

Once clicking a download button, files will be downloaded. Before executing next code, it needs to wait until the download completes.

单击下载按钮后,将下载文件。在执行下一段代码之前,需要等待下载完成。

My code looks like this:

我的代码如下所示:

Thread.sleep(2000);
driver.findElement(By.xpath("//*[@id='perform']")).click();//click for download

Thread.sleep(20000);
//code to be executed after download completes
Readfile fileobj=new Readfile();
String checkfile=fileobj.checkfilename();

How can I make the webdriver wait until a download completes?

如何让 webdriver 等待下载完成?

回答by olyv

Well, your file is stored somewhere, right? So, check if it exists in file system

好吧,您的文件存储在某个地方,对吗?所以,检查它是否存在于文件系统中

File f = new File(filePathString);

do {
  Thread.sleep(3000);
} while (f.exists() && f.length() == expectedSizeInBytes)

回答by Mark Boxall

Some operating systems (e.g. Mac OS X) don't set the filename until the download is complete. So it seems sufficient to use a wait or a while loop to check for the file to exist.

某些操作系统(例如 Mac OS X)在下载完成之前不会设置文件名。因此,使用wait 或while 循环来检查文件是否存在似乎就足够了。

e.g.

例如

File file = new File(fullPathToFile);
while (!file.exists()) {
    Thread.sleep(1000);
}

回答by Erica King

do {

   filesize1 = f.length();  // check file size
   Thread.sleep(5000);      // wait for 5 seconds
   filesize2 = f.length();  // check file size again

} while (length2 != length1); 

where f is a File, filesize is long

其中 f 是文件,文件大小很长

回答by spatel4140

A little late but this question has a good number of views, I thought it would be worth the time to answer it in case you haven't moved on or someone else comes across it.

有点晚了,但这个问题有很多观点,我认为如果你没有继续前进或其他人遇到它,我认为值得花时间回答它。

I too ran into the same problem and thought I'd share. I was developing in python at the time but the same concept applies. You don't have to do the actual download using selenium. Rather than clicking on the element to start the download, you should consider retrieving the link and using built in functions to proceed from there.

我也遇到了同样的问题,并认为我会分享。我当时正在用 python 开发,但同样的概念也适用。您不必使用 selenium 进行实际下载。与其单击元素开始下载,不如考虑检索链接并使用内置函数从那里继续。

The element you would normally click to begin the download should have a 'href' attribute that you should be able to read using selenium. This is the url pointing to the actual file. In python, it looks something like this:

您通常单击开始下载的元素应该有一个“href”属性,您应该能够使用 selenium 读取该属性。这是指向实际文件的 url。在python中,它看起来像这样:

    element = driver.find_element_by_id('dl_link')
    url = element.get_attribute('href')

From here you can use an http library to call the url. The important part here is that you set 'stream' to true so you can begin writing the bytes to a file. Make sure the file path contains the correct file extension and another thing, most operating systems don't allow you to name files with certain characters such as back slashes or quotations so heads up on that.

从这里您可以使用 http 库来调用 url。这里的重要部分是您将 'stream' 设置为 true,以便您可以开始将字节写入文件。确保文件路径包含正确的文件扩展名和另一件事,大多数操作系统不允许您使用某些字符(例如反斜杠或引号)命名文件,因此请注意这一点。

def download_file(url, file_path):
    from requests import get
    reply = get(url, stream=True)
    with open(file_path, 'wb') as file:
        for chunk in reply.iter_content(chunk_size=1024): 
            if chunk:
                file.write(chunk)

The program shouldn't continue until the download is complete making it no longer necessary to poll until it is complete.

程序在下载完成之前不应继续,因此在完成之前不再需要轮询。

I apologize for answering in a different language, in Java I believe you can use the HttpURLConnection API. Hope this helps!

我很抱歉用不同的语言回答,在 Java 中我相信你可以使用 HttpURLConnection API。希望这可以帮助!

回答by Alexander Arendar

I use Scala for my automation but the port to Java should be trivial since I use java Selenium classes there anyway. So, first you need this:

我将 Scala 用于我的自动化,但到 Java 的端口应该是微不足道的,因为我在那里使用了 java Selenium 类。所以,首先你需要这个:

import com.google.common.base.Function
import java.nio.file.{Files, Paths, Path}

def waitUntilFileDownloaded(timeOutInMillis:Int)={
    val wait:FluentWait[Path] = new FluentWait(Paths.get(downloadsDir)).withTimeout(timeOutInMillis, TimeUnit.MILLISECONDS).pollingEvery(200, TimeUnit.MILLISECONDS)
    wait.until(
      new Function[Path, Boolean] {
        override def apply(p:Path):Boolean = Files.list(p).iterator.asScala.size > 0
      }
    )
  }

Then in my test suite where I need to download xls file I just have this:

然后在我需要下载 xls 文件的测试套件中,我只有这个:

def exportToExcel(implicit driver: WebDriver) = {
    click on xpath("//div[contains(@class, 'export_csv')]")
    waitUntilFileDownloaded(2000)
  }

I hope you've got the idea. FluentWait is very useful abstraction and though it is a part of Selenium it can be used wherever you need to wait with polling till some condition is met.

我希望你有这个想法。FluentWait 是非常有用的抽象,虽然它是 Selenium 的一部分,但它可以用于任何需要等待轮询直到满足某些条件的地方。

回答by Leon

A java adaptation of Alexander Arendar's idea :

Alexander Arendar 想法的 Java 改编版:

(using Java 8 & the predicate version of until method of FluentWait)

(使用 Java 8 和 FluentWait 的 until 方法的谓词版本)

  private void waitForFileDownload(int totalTimeoutInMillis, String expectedFileName) throws IOException {  
            FluentWait<WebDriver> wait = new FluentWait(this.funcDriver.driver)
                                   .withTimeout(totalTimeoutInMillis, TimeUnit.MILLISECONDS)
                                   .pollingEvery(200, TimeUnit.MILLISECONDS);
            File fileToCheck = getDownloadsDirectory()
                               .resolve(expectedFileName)
                               .toFile();

            wait.until((WebDriver wd) -> fileToCheck.exists());

        }


public synchronized Path getDownloadsDirectory(){
        if(downloadsDirectory == null){

            try {
                downloadsDirectory = Files.createTempDirectory("selleniumdownloads_");
            } catch (IOException ex) {
                throw new RuntimeException("Failed to create temporary downloads directory");
            }
        }
        return downloadsDirectory;
    }

Note the use of createTempDirectory to avoid the caveats of recursively deleting more than intended as well as automatically safely disposing of the folder when we re done with it.

请注意使用 createTempDirectory 避免递归删除超出预期的警告,以及在我们完成文件夹时自动安全地处理文件夹。

回答by vins

I like awaitility

我喜欢等待

    Path filePath = Paths.get(".", "filename");
    await().atMost(1, MINUTES)
            .ignoreExceptions()
            .until(() -> filePath.toFile().exists());

More info : http://www.testautomationguru.com/selenium-webdriver-how-to-wait-for-expected-conditions-using-awaitility/

更多信息:http: //www.testautomationguru.com/selenium-webdriver-how-to-wait-for-expected-conditions-using-awaitility/

回答by Mani P

The below code is working fine for me.

下面的代码对我来说工作正常。

Also no warning will be as I used Generic type and Duration as recommended.

也不会发出警告,因为我按照建议使用了通用类型和持续时间。

File file = new File("C:\chromedriver_win32.zip"); FluentWait wait = new FluentWait(driver).withTimeout(Duration.ofSeconds(25)).pollingEvery(Duration.ofMillis(100)); wait.until( x -> file.exists());

File file = new File("C:\chromedriver_win32.zip"); FluentWait wait = new FluentWait(driver).withTimeout(Duration.ofSeconds(25)).pollingEvery(Duration.ofMillis(100)); wait.until( x -> file.exists());

回答by supputuri

If you are using chrome for the download, the you can use the below method to make sure the script will wait until the download is completed.

如果您使用 chrome 进行下载,您可以使用以下方法确保脚本将等待下载完成。

Python Implementation:

Python实现:

def waitUntilDownloadCompleted(maxTime=600):
    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() + maxTime
    while True:
        try:
            # get the download 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:
                # exit the method once it's completed
                return downloadPercentage
        except:
            pass
        # wait for 1 second before checking the percentage next time
        time.sleep(1)
        # exit method if the download not completed with in MaxTime.
        if time.time() > endTime:
            break

Just call the method when ever you click on download link/button.

只需在单击下载链接/按钮时调用该方法。

# click on download button
driver.find_element_by_xpath("//*[@id='perform']").click()
#wait until the download completed
waitUntilDownloadCompleted(120) #2 minutes

回答by Daddy Cool

import time
from os import walk

download_dir = 'path\to\download\folder'


def check_if_download_folder_has_unfinished_files():
    for (dirpath, dirnames, filenames) in walk(download_dir):
        return str(filenames)


def wait_for_files_to_download():
    time.sleep(5)  # let the driver start downloading
    file_list = check_if_download_folder_has_unfinished_files()
    while 'Unconfirmed' in file_list or 'crdownload' in file_list:
        file_list = check_if_download_folder_has_unfinished_files()
        time.sleep(1)


if __name__ == '__main__':
    wait_for_files_to_download()