如何使用Selenium Webdriver和Firefox检测所有下载的时间

时间:2017-11-23 19:13:17

标签: vb.net selenium firefox selenium-webdriver selenium-firefoxdriver

我有一个FirefoxDriver实例,可以执行多个操作并开始下载多个文件。这些文件可能有各种大小,当它完成循环并关闭时,它会中断未完成的下载。有没有办法可以检查是否有待处理的下载,然后在关闭Firefox窗口之前等待它们全部完成?这适用于VB.NET,但我也能理解C#解决方案。谢谢!

2 个答案:

答案 0 :(得分:2)

Firefox和Chrome在下载文件时创建和中间文件扩展名。对于chrome它的 crdownload ,我不记得Firefox的用途。但是,您可以下载大文件并进行检查。下载完成后,此中间文件将重命名为实际文件名。

您只需要编写一个代码来检查是否存在任何带有crdownload扩展名的文件。如果没有,您的下载完成。

答案 1 :(得分:1)

使用Firefox,可以在浏览器级别注入一些JavaScript,这意味着您几乎可以做任何事情。但是设置上下文的命令没有在.Net客户端中实现,因此您必须扩展该类。

此示例等待至少一次下载并使所有下载成功,然后返回每个文件的完整路径:

var options = new FirefoxOptions();
options.SetPreference("browser.download.dir", "C:\\temp");
options.SetPreference("pdfjs.disabled", true);
options.SetPreference("pdfjs.enabledCache.state", false);
options.SetPreference("browser.download.folderList", 2);
options.SetPreference("browser.download.useDownloadDir", true);
options.SetPreference("browser.helperApps.neverAsk.saveToDisk", "application/pdf");

var driver = new FirefoxDriverEx(options);
driver.Url = "https://support.mozilla.org/en-US/kb/use-adobe-reader-view-pdf-files-firefox";
driver.FindElementByCssSelector("[href*='mozilla_privacypolicy.pdf']").Click();

string[] files = driver.GetDownloads(1, TimeSpan.FromSeconds(120));
class FirefoxDriverEx : FirefoxDriver {

    public FirefoxDriverEx(FirefoxOptions options) : base(options) {
        var commands = CommandExecutor.CommandInfoRepository;
        commands.TryAddCommand("SetContext", new CommandInfo("POST", "/session/{sessionId}/moz/context"));
    }

    public string[] GetDownloads(int minimum, TimeSpan timeout) {
        const string JS_GET_DOWNLOADS = @"
          var minimum = arguments[0], callback = arguments[1];
          Components.utils.import('resource://gre/modules/Downloads.jsm', {}).Downloads
            .getList(Downloads.ALL).then(list => list.getAll())
            .then(items => items.length >= minimum && items.every(e => e.succeeded) ? items.map(e => e.target.path) : null)
            .then(callback);";

        try {
            SetContext("chrome");

            for (var endtime = DateTime.UtcNow + timeout; ; Thread.Sleep(1000)) {
                Object result = ExecuteAsyncScript(JS_GET_DOWNLOADS, minimum);
                if (result != null)
                    return ((IEnumerable<object>)result).Cast<string>().ToArray();
                if (DateTime.UtcNow > endtime)
                    throw new TimeoutException("No download available or one is not complete.");
            }
        } finally {
            SetContext("content");
        }
    }

    public void SetContext(string context) {
        var parameters = new Dictionary<string, object> { { "context", context } };
        CommandExecutor.Execute(new Command(this.SessionId, "SetContext", parameters));
    }
}