Удаленка для jenkins+selenide+selenoid+allure+docker спецов на 2-3 часа в день. 100% remote! Присоединиться к проекту

Как указать папку для загрузки файлов Chrome в режиме headless ?

upload
headless
configuration
chrome
webdriver
python
Теги: #<Tag:0x00007fedc03f5b00> #<Tag:0x00007fedc03f59c0> #<Tag:0x00007fedc03f5808> #<Tag:0x00007fedc03f56a0> #<Tag:0x00007fedc03f5560> #<Tag:0x00007fedc03f53d0>

(Вадим) #1

Для хрома в обычном режиме можно добавить опцию и указать папку для файлов которые будут загружатся:

prefs = { “profile.default_content_settings.popups” : 0,
"download.default_directory" : os.getcwd() + “/path_to_folder/” ,
"directory_upgrade" : True }
chrome_options.add_experimental_option( “prefs” , prefs)

Но в режиме headless она не срабатывает. На StackOverflow есть подобные темы, но без решения, а если и написаны, они не рабочие. Кто-то сталкивался с такой проблемой, может есть какой-то хук для решения задачи ?


(Bohdan B) #2

Есть решение описаное для Ruby, но актуально для любого языка - прокинуть путь через Dev tools protocol https://bugs.chromium.org/p/chromium/issues/detail?id=696481#c78


(Сергей Кузьмин) #3

вас не затруднит привести snippet, уже на java , .net или js ?


(Bohdan B) #4

Перевод c ruby

const { id_ } = await driver.getSession()
const body = {
    "cmd": "Page.setDownloadBehavior",
    "params": {
        "behavior": "allow",
        "downloadPath": "users/blablabla/",
    }
}
await fetch(`http://localhost:4444/wd/hub/session/${id_}/chromium/send_command`, {
    method: 'POST',
    body: JSON.stringify(body),
    headers: { 'Content-Type': 'application/json' }
})

(Alexandr D ) #5

C#:

  if (IsHeadless && BrowserType.ToLower() == "chrome")
            {
                var sessionId = DriverThreadLocal.Value.GetSessionId();
                var cmd2Driver = new CmdToDriver
                {
                    cmd = "Page.setDownloadBehavior",
                    ParamsInfo = new CmdToDriver.Params
                    {
                        behavior = "allow",
                        downloadPath = DowndloadFolder.FullName
                    }
                };
                var json = JsonConvert.SerializeObject(cmd2Driver);
                var port = cds?.Port;
                var url = $"http://localhost:{port}/session/{sessionId}/chromium/send_command";
                var request = new RestRequest(Method.POST);
                request.AddParameter("application/json", json, ParameterType.RequestBody);
                request.AddHeader("Content-Type", "application/json");
                request.RequestFormat = DataFormat.Json;
                ApiManager.SendRequest<object>(url, request);


            }
        }

        public class CmdToDriver
        {
            public string cmd { get; set; }
            [JsonProperty(PropertyName = "params")]
            public Params ParamsInfo {get; set; }

            public class Params
            {
                public string behavior { get; set; }
                public string downloadPath { get; set; }
            }
        }

 public static string GetSessionId(this IWebDriver driver)
        {
            return ((RemoteWebDriver) driver).SessionId.ToString();
        }

(Сергей Кузьмин) #6

сапсибо

пример на офмф:
// based on:
// https://stackoverflow.com/questions/48049359/download-files-in-java-selenium-using-chromedriver-and-headless-mode

import org.json.JSONException;
import org.json.JSONObject;

private static final String chomeDriverPath =  ...;
	private static final String downloadFilepath = ...;

...
		ChromeDriverService chromeDriverSevice = new ChromeDriverService.Builder()
				.usingDriverExecutable(new File(chomeDriverPath)).usingAnyFreePort()
				.build();
		chromeDriverSevice.start();

		driver = new ChromeDriver(chromeDriverSevice, 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", downloadFilepath);
		commandParams.put("params", params);
		JSONObject commandParamsObj = new JSONObject(commandParams);

		HttpClient httpClient = HttpClientBuilder.create().build();
		String payload = commandParamsObj.toString();

		String u = chromeDriverSevice.getUrl().toString() + "/session/"
				+ driver.getSessionId() + "/chromium/send_command";
		HttpPost request = new HttpPost(u);
		request.addHeader("content-type", "application/json");
		request.setEntity(new StringEntity(payload));
		httpClient.execute(request);

		driver.manage().timeouts().implicitlyWait(4, TimeUnit.SECONDS);
	}


	@Test
	public void testDownload() throws Exception {
		driver.get("http://www.seleniumhq.org/download/");
		driver.findElement(By.linkText("32 bit Windows IE")).click();
	}



(Вадим) #7

А на python кода нету ?)


(Dmitry Boytsov) #8
 def enable_download_in_headless_chrome(br, download_dir):
        # add missing support for chrome "send_command"  to selenium webdriver
        br.command_executor._commands["send_command"] = ("POST", '/session/$sessionId/chromium/send_command')

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

chromeOptions = webdriver.ChromeOptions()
prefs = {'download.default_directory': path_for_downloads, "download.prompt_for_download": False}
chromeOptions.add_experimental_option("prefs", prefs)
if chrome_args != "":
     chromeOptions.add_argument("--headless")
browser = webdriver.Chrome(chrome_driver, chrome_options=chromeOptions)
browser = enable_download_in_headless_chrome(browser, path_for_downloads)

(Вадим) #9

Спасибо !