Chromium/Chrome 无头模式 - 文件下载不起作用?

19

我下载了最新版本的Chromium,以测试其无界面特性。

当我运行以下命令(作为root用户,因为我仍在测试):

./chrome --no-sandbox http://cp7.awardspace.com/speed-test/awardspace-data1mb.zip
在GUI终端中,它会打开Chromium并下载文件。
如果我要在无头模式下运行,我需要输入以下内容:
./chrome --no-sandbox --headless http://cp7.awardspace.com/speed-test/awardspace-data1mb.zip

终端输出一些信息,没有窗口打开,但是也意味着:我没有将文件下载到任何地方。

我搜索了互联网和讨论组以获取更多信息,但找不到任何内容。

在无头模式下,Chromium的文件下载功能是否不起作用?


1
这个解决方案对我非常有效(Python)。 - applekate
7个回答

13

5

使用 ChromeDriverService 和 POST session/{sessionId}/chromium/send_command

POST 请求的 JSON 数据:

{
    "cmd": "Page.setDownloadBehavior",
    "params": {
        "behavior": "allow",
        "downloadPath": "C:\\Download\\Path"
    }
}

C#解决方案

添加对System.Net.Http的引用,并使用NuGet安装Newtonsoft.JSON。

public static IWebDriver Driver { get; private set; }

public void SetDriver()
{
    var chromeOptions = new ChromeOptions();
    chromeOptions.AddArguments("--headless", "--window-size=1920,1080");

    var driverService = ChromeDriverService.CreateDefaultService();
    Driver = new ChromeDriver(driverService, chromeOptions);

    Task.Run(() => AllowHeadlessDownload(driverService));
}

static async Task AllowHeadlessDownload(ChromeDriverService driverService )
{
    var jsonContent = new JObject(
        new JProperty("cmd", "Page.setDownloadBehavior"),
        new JProperty("params",
        new JObject(new JObject(
            new JProperty("behavior", "allow"),
            new JProperty("downloadPath", @"C:\Download\Path")))));
    var content = new StringContent(jsonContent.ToString(), Encoding.UTF8, "application/json");
    var sessionIdProperty = typeof(ChromeDriver).GetProperty("SessionId");
    var sessionId = sessionIdProperty.GetValue(Driver, null) as SessionId;

    using (var client = new HttpClient())
    {
        client.BaseAddress = driverService.ServiceUrl;
        var result = await client.PostAsync("session/" + sessionId.ToString() + "/chromium/send_command", content);
        var resultContent = await result.Content.ReadAsStringAsync();
    }
}

4
在Java中使用以下代码:
System.setProperty("webdriver.chrome.driver", "/usr/local/bin/chromedriver");
         ChromeOptions options = new ChromeOptions();
                options.addArguments("--test-type");
                options.addArguments("--headless");
                options.addArguments("--disable-extensions"); //to disable browser extension popup

                ChromeDriverService driverService = ChromeDriverService.createDefaultService();
                ChromeDriver driver = new ChromeDriver(driverService, options);

                Map<String, Object> commandParams = new HashMap<>();
                commandParams.put("cmd", "Page.setDownloadBehavior");
                Map<String, String> params = new HashMap<>();
                params.put("behavior", "allow");
                params.put("downloadPath", "//home//vaibhav//Desktop");
                commandParams.put("params", params);
                ObjectMapper objectMapper = new ObjectMapper();
                HttpClient httpClient = HttpClientBuilder.create().build();
                String command = objectMapper.writeValueAsString(commandParams);
                String u = driverService.getUrl().toString() + "/session/" + driver.getSessionId() + "/chromium/send_command";
                HttpPost request = new HttpPost(u);
                request.addHeader("content-type", "application/json");
                request.setEntity(new StringEntity(command));
                httpClient.execute(request);
        driver.get("http://www.seleniumhq.org/download/");
        driver.findElement(By.linkText("32 bit Windows IE")).click();

9
您可能希望对这段代码进行详细的分解说明,仅给出一大段没有解释的代码并不会对提问者有所帮助。 - Verv
Chrome和Chrome驱动程序的版本? - Apurv

2

以下代码适用于使用ChromeDriver 2.46的C#

    private ChromeDriver GetDriver()
    {
        var options = new ChromeOptions();

        options.AddArguments("headless");
        options.AddUserProfilePreference("download.prompt_for_download", "false");
        options.AddUserProfilePreference("download.directory_upgrade", "true");
        options.AddUserProfilePreference("download.prompt_for_download", "false");
        options.AddUserProfilePreference("safebrowsing.enabled", "false");
        options.AddUserProfilePreference("safebrowsing.disable_download_protection", "true");

        options.AddArguments("--disable-web-security");

        var curr = Directory.GetCurrentDirectory();
        options.AddUserProfilePreference("download.default_directory", curr);

        var driver = new ChromeDriver(options);
        Log.Info($"Started Chrome Driver with options: {options.ToJsonNoTypes()}");

        var param = new Dictionary<string, object>();
        param.Add("behavior", "allow");
        param.Add("downloadPath", curr);
        driver.ExecuteChromeCommand("Page.setDownloadBehavior", param);

        return driver;
    }

1
很好 - 这对我有用。许多其他答案仅仅谈到发送Page.setDownloadBehavior命令,而没有设置其他配置文件首选项。 - Brendan Green
我们需要添加一个类才能使“ExecuteChromeCommand”正常工作吗? - Nina

0

我能够通过Chrome远程接口使用Chrome无头浏览器下载文件

public void TryEnableFileDownloading(string downloadPath)
{
    TrySendCommand("Page.setDownloadBehavior", new Dictionary<string, object>()
    {
        ["behavior"] = "allow",
        ["downloadPath"] = downloadPath
    });
}

完整的与Selenium集成的代码可以在这里找到 https://github.com/cezarypiatek/Tellurium/blob/master/Src/MvcPages/SeleniumUtils/ChromeRemoteInterface/ChromeRemoteInterface.cs

有关setDownloadBehavior和Chrome远程接口的更多信息 https://chromedevtools.github.io/devtools-protocol/tot/Page/#method-setDownloadBehavior


@Coded9 我已经有8年没有写Java代码了,所以重写代码并设置环境可能需要我很长时间。关键点在于访问WebDriver的私有字段CommandExecutor。我不知道Java在反射方面提供了哪些可能性。如果您能够访问私有成员,那么您应该能够轻松地自己实现此功能。有关更多详细信息,请查看我的存储库中WebDriverCommandExecuter类的实现,它允许我通过WebDriver使用ChromeRemoteInterface。 - cezarypiatek

0
注意:这不是问题的确切答案,但可以解决问题。
我在研究如何使用不同的参数/选项/首选项使无头Chrome下载时,尝试了很多方法,但都没有成功。然后我使用了标准的Java文件下载方式,使用了Apache Commons的FileUtils。
FileUtils.copyURLToFile(URI, FILE);

0

我今天在Windows 10上使用IdeaJ编辑器、Java和Maven尝试了一下,一切正常:

                ChromeOptions ds = getDesiredCapabilities(browserName);

                ChromeDriverService driverService = ChromeDriverService.createDefaultService();
                ChromeDriver driver = new ChromeDriver(driverService, ds);

                Map<String, Object> commandParams = new HashMap<>();
                commandParams.put("cmd", "Page.setDownloadBehavior");

                Map<String, String> params = new HashMap<>();
                params.put("behavior", "allow");
                params.put("downloadPath", System.getProperty("user.home") + File.separator + "Downloads");
                commandParams.put("params", params);

                ObjectMapper objectMapper = new ObjectMapper();
                HttpClient httpClient = HttpClientBuilder.create().build();

                String command = objectMapper.writeValueAsString(commandParams);

                String u = driverService.getUrl().toString() + "/session/" + driver.getSessionId() + "/chromium/send_command";

                HttpPost request = new HttpPost(u);
                request.addHeader("content-type", "application/json");
                request.setEntity(new StringEntity(command));
                httpClient.execute(request);

使用配置的“driver”实例,通过URL或Json / AngularJs下载操作导航到下载文件。 有时由于网络缓慢而下载时会出现损坏文件的情况。
此外,相同的配置将适用于Google Chrome UI或最新Chrome驱动程序77的无头执行。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接