如何使用远程selenium webdriver下载文件?

如何使用远程selenium webdriver下载文件?,selenium,selenium-webdriver,Selenium,Selenium Webdriver,我正在使用远程seleniumwebdriver执行一些测试。然而,在某些时候,我需要下载一个文件并检查其内容 我使用的远程Web驱动程序如下所示(在python中): 使用“普通”网络驱动程序,我可以在本地计算机上下载文件而不会出现问题。然后,我可以使用测试代码来验证下载文件的内容(根据测试参数可能会发生变化)。这不是对下载本身的测试,但我需要一种方法来验证生成的文件的内容 但是如何使用远程网络驱动程序来实现这一点呢?我在任何地方都找不到任何有用的东西…Webdriver: 如果您使用的是we

我正在使用远程
selenium
webdriver执行一些测试。然而,在某些时候,我需要下载一个文件并检查其内容

我使用的远程Web驱动程序如下所示(在
python
中):

使用“普通”网络驱动程序,我可以在本地计算机上下载文件而不会出现问题。然后,我可以使用测试代码来验证下载文件的内容(根据测试参数可能会发生变化)。这不是对下载本身的测试,但我需要一种方法来验证生成的文件的内容

但是如何使用远程网络驱动程序来实现这一点呢?我在任何地方都找不到任何有用的东西…

Webdriver: 如果您使用的是webdriver,则表示您的代码使用内部Selenium客户端和服务器代码与浏览器实例通信。下载的文件存储在本地机器中,可以使用java、python、.Net、node.js等语言直接访问

远程Web驱动程序[Selenium Grid]: 如果您使用的是远程webdriver,则意味着您使用的是网格概念,网格的主要用途是
将测试分发到多台机器或虚拟机(VM)
。在这种情况下,您的代码使用Selenium客户端与Selenium Grid Server通信,后者使用指定的浏览器将指令传递给注册节点。表单的网格节点将从特定于浏览器的驱动程序向浏览器实例传递指令此处下载到该系统的
文件系统|硬盘
,但用户无法访问运行浏览器的虚拟机上的文件系统。

  • 通过使用javascript,如果我们可以访问该文件,那么我们就可以访问并返回到客户机代码。但出于安全原因,Javascript不允许从磁盘读取文件

  • 如果Selenium Grid hub和节点位于同一系统中,并且它们位于公共网络中,则您可以将下载文件的路径更改为一些公共下载路径,如
    。/Tomcat/webapps/Root/CutrentTimeFolder/file.pdf
    。通过使用公共URL,您可以直接访问该文件

例如,从tomcat的根文件夹下载文件[]

System.out.println(“FireFox驱动程序路径«”+geckodriverCloudRootPath);
File temp=File.createTempFile(“geckodriver”,null);
临时设置可执行文件(真);
copyrltofile(新的URL(geckodriverCloudRootPath),temp);
System.setProperty(“webdriver.gecko.driver”,temp.getAbsolutePath());
能力。设置能力(“木偶”,真);
  • 如果Selenium网格集线器和节点不在同一系统中,您可能无法获得下载的文件,因为网格集线器将位于公共网络
    [WAN]
    中,而节点将位于组织的专用网络
    [LAN]
您可以将浏览器的下载文件路径更改为硬盘上的指定文件夹。通过使用下面的代码

String downloadFilepath=“E:\\download”;
HashMap chromePrefs=新HashMap();
chromePrefs.put(“profile.default\u content\u settings.popups”,0);
chromePrefs.put(“download.default\u目录”,downloadFilepath);
ChromeOptions选项=新的ChromeOptions();
HashMap chromeOptionsMap=新HashMap();
选项。设置实验选项(“prefs”,chromePrefs);
options.addArguments(“--test type”);
options.addArguments(“--disable extensions”)//禁用浏览器扩展弹出窗口
DesiredCapabilities=DesiredCapabilities.chrome();
cap.setCapability(ChromeOptions.CAPABILITY,ChromeOptions sMap);
cap.setCapability(CapabilityType.ACCEPT_SSL_CERTS,true);
上限设置能力(色度选项、能力、选项);
RemoteWebDriver=新的ChromeDriver(cap);
@看


Selenium API不提供在远程机器上下载文件的方法

但根据浏览器的不同,单独使用Selenium仍然是可能的

使用Chrome,可通过导航
chrome://downloads/
并在页面中使用注入的
检索:

从selenium导入webdriver
从selenium.webdriver.support.ui导入WebDriverWait
导入操作系统、时间、base64
def get_下载的_文件(驱动程序):
如果不是驱动程序。当前\u url.startswith(“chrome://downloads"):
驱动程序。获取(“chrome://downloads/")
返回驱动程序。执行_脚本(\
“返回downloads.Manager.get().items\ux”
“.filter(e=>e.state=='COMPLETE')”
“.map(e=>e.filePath | | e.file_path);”)
def get_文件内容(驱动程序、路径):
elem=驱动程序。执行脚本(\
“var input=window.document.createElement('input')
input.setAttribute('type','file')
“input.hidden=true;”
“input.onchange=函数(e){e.stopPropagation()};”
“返回窗口.document.documentElement.appendChild(输入);”)
元素执行('sendKeysElement',{'value':[path],'text':path})
结果=驱动程序。执行异步脚本(\
变量输入=参数[0],回调=参数[1]
“var reader=new FileReader();”
“reader.onload=函数(ev){callback(reader.result)};”
“reader.onerror=函数(ex){callback(ex.message)};”
“reader.readAsDataURL(input.files[0])
“input.remove();”
,elem)
如果不是,则返回result.startswith('data:'):
引发异常(“未能获取文件内容:%s”%result)
返回base64.b64decode(结果[result.find('base64'))+7:]
功能_chrome={\
'browserName':'chrome',
#'代理':{\
#“proxyType”:“手动”,
#‘sslProxy’:‘50.59.162.78:8088’,
#“httpProxy”:“50.59.162.78:8088”
# },
'goog:chromeOptions':{\
“args”:[
],
“prefs”:{\
#“下载.默认目录”:“,
#'download.directory\u upgrade':True,
'download.prompt_for_download':False,
“plugins.always\u open\u pdf\u外部”:True,
PROXY = ...

prefs = {
    "profile.default_content_settings.popups":0,
    "download.prompt_for_download": "false",
    "download.default_directory": os.getcwd(),
}
chrome_options = Options()
chrome_options.add_argument("--disable-extensions")
chrome_options.add_experimental_option("prefs", prefs)

webdriver.DesiredCapabilities.CHROME['proxy'] = {
  "httpProxy":PROXY,
  "ftpProxy":PROXY,
  "sslProxy":PROXY,
  "noProxy":None,
  "proxyType":"MANUAL",
  "class":"org.openqa.selenium.Proxy",
  "autodetect":False
}
driver = webdriver.Remote(
        command_executor='http://aaa.bbb.ccc:4444/wd/hub',
        desired_capabilities=DesiredCapabilities.CHROME)
public class CustomFirefoxDriver extends RemoteWebDriver{


    public CustomFirefoxDriver(URL RemoteWebDriverUrl, FirefoxOptions options) throws Exception {
        super(RemoteWebDriverUrl, options);
        CommandInfo cmd = new CommandInfo("/session/:sessionId/moz/context", HttpMethod.POST);
        Method defineCommand = HttpCommandExecutor.class.getDeclaredMethod("defineCommand", String.class, CommandInfo.class);
        defineCommand.setAccessible(true);
        defineCommand.invoke(super.getCommandExecutor(), "SET_CONTEXT", cmd);
    }


    public Object setContext(String context) {
        return execute("SET_CONTEXT", ImmutableMap.of("context", context)).getValue();
    }
}
public String getDownloadedFileNameBySubStringFirefox(String Matcher) {

    String fileName = "";

    ((CustomFirefoxDriver) driver).setContext("chrome");

    String script = "var { Downloads } = Components.utils.import('resource://gre/modules/Downloads.jsm', {});"
            + "Downloads.getList(Downloads.ALL).then(list => list.getAll())"
            + ".then(entries => entries.filter(e => e.succeeded).map(e => e.target.path))"
            + ".then(arguments[0]);";

    String fileNameList = js.executeAsyncScript(script).toString();
    String name = fileNameList.substring(1, fileNameList.length() -1);

    if(name.contains(Matcher)) {
        fileName = name;
    }

    ((CustomFirefoxDriver) driver).setContext("content");

    return fileName;
}

public void getDownloadedFileContentFirefox(String fileIdentifier) {

    String filePath = getDownloadedFileNameBySubStringFirefox(fileIdentifier);
    ((CustomFirefoxDriver) driver).setContext("chrome");

    String script = "var { OS } = Cu.import(\"resource://gre/modules/osfile.jsm\", {});" + 
                    "OS.File.read(arguments[0]).then(function(data) {" + 
                    "var base64 = Cc[\"@mozilla.org/scriptablebase64encoder;1\"].getService(Ci.nsIScriptableBase64Encoder);" +
                    "var stream = Cc['@mozilla.org/io/arraybuffer-input-stream;1'].createInstance(Ci.nsIArrayBufferInputStream);" +
                    "stream.setData(data.buffer, 0, data.length);" +
                    "return base64.encodeToString(stream, data.length);" +
                    "}).then(arguments[1]);" ;

    Object base64FileContent = js.executeAsyncScript(script, filePath);//.toString();
    try {
        Files.write(Paths.get("temp.xls"), DatatypeConverter.parseBase64Binary(base64FileContent.toString()));
    } catch (IOException i) {
        System.out.println(i.getMessage());
    }

}
public String getDownloadedFileNameBySubStringChrome(String Matcher) {
    String file = "";
    //The script below returns the list of files as a list of the form '[$FileName1, $FileName2...]'
    // with the most recently downloaded file listed first.
    String script = "return downloads.Manager.get().items_.filter(e => e.state === 'COMPLETE').map(e => e.file_url);" ;
    if(!driver.getCurrentUrl().startsWith("chrome://downloads/")) {
        driver.get("chrome://downloads/");
        }
    String fileNameList =  js.executeScript(script).toString();
    //Removing square brackets
    fileNameList = fileNameList.substring(1, fileNameList.length() -1);
    String [] fileNames = fileNameList.split(",");
    for(int i=0; i<fileNames.length; i++) {
        if(fileNames[i].trim().contains(Matcher)) {
            file = fileNames[i].trim();
            break;
        }
    }

    return file;

}


public void getDownloadedFileContentChrome(String fileIdentifier) {

    //This causes the user to be navigated to the Chrome Downloads page
    String fileName = getDownloadedFileNameBySubStringChrome(fileIdentifier);
    //Remove "file://" from the file path
    fileName = fileName.substring(7);

    String script =  "var input = window.document.createElement('INPUT'); " +
            "input.setAttribute('type', 'file'); " +
            "input.setAttribute('id', 'downloadedFileContent'); " +
            "input.hidden = true; " +
            "input.onchange = function (e) { e.stopPropagation() }; " +
            "return window.document.documentElement.appendChild(input); " ;
    WebElement fileContent = (WebElement) js.executeScript(script);
    fileContent.sendKeys(fileName);

    String asyncScript = "var input = arguments[0], callback = arguments[1]; " +
            "var reader = new FileReader(); " +
            "reader.onload = function (ev) { callback(reader.result) }; " +
            "reader.onerror = function (ex) { callback(ex.message) }; " +
            "reader.readAsDataURL(input.files[0]); " +
            "input.remove(); " ;

    String content = js.executeAsyncScript(asyncScript, fileContent).toString();
    int fromIndex = content.indexOf("base64,") +7 ;
    content = content.substring(fromIndex);

    try {
        Files.write(Paths.get("temp.xls"), DatatypeConverter.parseBase64Binary(content));
    } catch (IOException i) {
        System.out.println(i.getMessage());
    }

}
$downloaddir = "/tmp/";
$host = 'http://ipaddress:4444/wd/hub';
try {
    $options = new ChromeOptions();
    $options->setExperimentalOption("prefs",["safebrowsing.enabled" => "true", "download.default_directory" => $downloaddir]);
    $options->addArguments( array("disable-extensions",'safebrowsing-disable-extension-blacklist','safebrowsing-disable-download-protection') );
    $caps = DesiredCapabilities::chrome();
    $caps->setCapability(ChromeOptions::CAPABILITY, $options);
    $caps->setCapability("unexpectedAlertBehaviour","accept");
    $driver = RemoteWebDriver::create($host, $caps);
    $driver->manage()->window()->setPosition(new WebDriverPoint(500,0));
    $driver->manage()->window()->setSize(new WebDriverDimension(1280,1000));
    $driver->get("https://file-examples.com/index.php/sample-documents-download/sample-rtf-download/");
    sleep(1);
    $driver->findElement(WebDriverBy::xpath("//table//tr//td[contains(., 'rtf')]//ancestor::tr[1]//a"))->click();
    sleep(1);
    $driver->get('chrome://downloads/');
    sleep(1);
    // $inject = "return downloads.Manager.get().items_.filter(e => e.state === 'COMPLETE').map(e => e.filePath || e.file_path); ";
    $inject = "return document.querySelector('downloads-manager').shadowRoot.querySelector('downloads-item').shadowRoot.querySelector('a').innerText;";
    $filename = $driver->executeScript(" $inject" );
    echo "File name: $filename<br>";
    $driver->executeScript( 
        "var input = window.document.createElement('INPUT'); ".
        "input.setAttribute('type', 'file'); ".
        "input.hidden = true; ".
        "input.onchange = function (e) { e.stopPropagation() }; ".
        "return window.document.documentElement.appendChild(input); " );
    $elem1 = $driver->findElement(WebDriverBy::xpath("//input[@type='file']"));
    $elem1->sendKeys($downloaddir.$filename);
    $result = $driver->executeAsyncScript( 
        "var input = arguments[0], callback = arguments[1]; ".
        "var reader = new FileReader(); ".
        "reader.onload = function (ev) { callback(reader.result) }; ".
        "reader.onerror = function (ex) { callback(ex.message) }; ".
        "reader.readAsDataURL(input.files[0]); ".
        "input.remove(); "
        , [$elem1]);
    $coding = 'base64,';
    $cstart = strpos( $result, 'base64,' );
    if ( $cstart !== false ) 
        $result = base64_decode(substr( $result, $cstart + strlen($coding) ));
    echo "File content: <br>$result<br>";
    $driver->quit();
} catch (Exception $e) {
    echo 'Caught exception: ',  $e->getMessage(), "\n";
} 
def get_downloaded_files(driver):

  if not driver.current_url.startswith("chrome://downloads"):
    driver.get("chrome://downloads/")

  return driver.execute_script( \
     "return  document.querySelector('downloads-manager')  "
     " .shadowRoot.querySelector('#downloadsList')         "
     " .items.filter(e => e.state === 'COMPLETE')          "
     " .map(e => e.filePath || e.file_path || e.fileUrl || e.file_url); ")