Wait for Download to finish in selenium webdriver JAVA
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.
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:
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.
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!
do {
filesize1 = f.length(); // check file size
Thread.sleep(5000); // wait for 5 seconds
filesize2 = f.length(); // check file size again
} while (filesize1 != filesize2);
where f is a File, filesize is long
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:
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:
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.
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/
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)