How can I enable download a file using a headless

2019-03-04 00:40发布

问题:

How can i use Page.setDownloadBehavior in chrome dev tools to pass on so that I can set the download behavior for headless chrome with the code below?

    Create Chrome Browser
    [Arguments]    ${link_to_open}
    ${chrome_options}=    Evaluate    sys.modules['selenium.webdriver'].ChromeOptions()    sys, selenium.webdriver
    ${prefs}=    Create Dictionary    download.default_directory=${DOWNLOADS_DIR}
   Call Method    ${chrome options}    add_argument    headless 
   Call Method    ${chrome options}    add_argument    disable-gpu
  Selenium2Library.Go To    ${link_to_open}

回答1:

There appears to be a 'security feature' when trying to download a file using Chrome in headless mode. This is further discussed in the Chromium issue tracker. This pointed to the StackOverflow answer for Downloading with chrome headless and selenium. In this answer a Python example is given (GitHub) which converts easily to a Robot Framework Library:

headless_download.py

class headless_download(object):

    ROBOT_LIBRARY_VERSION = 1.0

    def __init__(self):
        pass

    def enable_download_in_headless_chrome(self, driver, download_dir):
        """
        there is currently a "feature" in chrome where
        headless does not allow file download: https://bugs.chromium.org/p/chromium/issues/detail?id=696481
        This method is a hacky work-around until the official chromedriver support for this.
        Requires chrome version 62.0.3196.0 or above.
        """

        # add missing support for chrome "send_command"  to selenium webdriver
        driver.command_executor._commands["send_command"] = ("POST", '/session/$sessionId/chromium/send_command')

        params = {'cmd': 'Page.setDownloadBehavior', 'params': {'behavior': 'allow', 'downloadPath': download_dir}}
        command_result = driver.execute("send_command", params)
        print("response from browser:")
        for key in command_result:
            print("result:" + key + ":" + str(command_result[key]))

When downloading a file, the StackOverlow answer for Robot Framework Download File that fits this example perfectly. Adding the extra lines for headless mode, additional library and a working example:

headless_download.robot

*** Settings ***
Test Teardown     Close All Browsers
Library           Selenium2Library
Library           OperatingSystem
Library           headless_download

*** Test Cases ***
Download PDF
  # create unique folder
  ${now}    Get Time    epoch
  ${download directory}    Join Path    ${OUTPUT DIR}    downloads_${now}
  Create Directory    ${download directory}

  ${chrome options}=    Evaluate    sys.modules['selenium.webdriver'].ChromeOptions()    sys, selenium.webdriver

  # list of plugins to disable. disabling PDF Viewer is necessary so that PDFs are saved rather than displayed
  ${disabled}    Create List    Chrome PDF Viewer
  ${prefs}    Create Dictionary    download.default_directory=${download directory}    plugins.plugins_disabled=${disabled}
  Call Method    ${chrome options}    add_experimental_option    prefs    ${prefs}

  Call Method    ${chrome options}    add_argument    headless 
  Call Method    ${chrome options}    add_argument    disable-gpu

  Create Webdriver    Chrome    chrome_options=${chrome options}

  Go To    http://www.sample-videos.com/download-sample-text-file.php

  ${S2L}           get library instance    Selenium2Library
  ${webdriver}    Call Method             ${S2L}    _current_browser
  Enable Download In Headless Chrome    ${webdriver}    ${download directory} 

  Click Link    xpath=//a[@data='1']

  # wait for download to finish
  ${file}    Wait Until Keyword Succeeds    1 min    2 sec    Download should be done    ${download directory}

*** Keywords ***
Download should be done
  [Arguments]    ${directory}
  [Documentation]    Verifies that the directory has only one folder and it is not a temp file.
  ...
  ...    Returns path to the file
  ${files}    List Files In Directory    ${directory}
  Length Should Be    ${files}    1    Should be only one file in the download folder
  Should Not Match Regexp    ${files[0]}    (?i).*\\.tmp    Chrome is still downloading a file
  ${file}    Join Path    ${directory}    ${files[0]}
  Log    File was successfully downloaded to ${file}
  [Return]    ${file}

So, in short: this answer was not possible without the contributions by others on Stack Overflow. If this provides you with a working solution, please follow the links to the other answers and upvote those answers as well.