2

I'm trying to automate a file download in headless chrome using Laravel/Dusk.In GUI mode,the file downloads just fine in my download folder.But in headless mode,the download does not take place at all.Is there any way to solve this issue?

Madhav Kurup
  • 23
  • 1
  • 5

3 Answers3

5

For those who come across this, I found a simple solution with the current version of Laravel at the time of writing this.

I suggest first creating a directory in your storage path called temp (probably want to gitignore this too), and then navigate to the DuskTestCase.php file setup with the Dusk installation.

Under the driver method, add the following under the section that initializes the ChromeOptions variable.

$options->setExperimentalOption('prefs', [
    'download.default_directory' => storage_path('temp')
]);

The driver function should now look like this:

$options = (new ChromeOptions())->addArguments([
    '--disable-gpu',
    '--headless',
    '--window-size=1920,1080'
]);

$options->setExperimentalOption('prefs', [
    'download.default_directory' => storage_path('temp')
]);

return RemoteWebDriver::create(
    'http://localhost:9515',
    DesiredCapabilities::chrome()->setCapability(
        ChromeOptions::CAPABILITY,
        $options
    )
);

As a side note, this worked for me with a PDF file created via JS, so I can't definitively say how this works with a file downloaded from the back-end.

Garrett
  • 353
  • 7
  • 14
0
public function testDownload($account){
    $this->browse(function (Browser $browser) {
        $download_path = storage_path('your/download/path');
        $url = $browser->driver->getCommandExecutor()->getAddressOfRemoteServer();
        $uri = '/session/' . $browser->driver->getSessionID() . '/chromium/send_command';
        $body = [
            'cmd' => 'Page.setDownloadBehavior',
            'params' => ['behavior' => 'allow', 'downloadPath' => $download_path]
        ];
        (new \GuzzleHttp\Client())->post($url . $uri, ['body' => json_encode($body)]);

        // Start your test
        $browser->visit("http://example.com/export")
        //your asserts here
}
  • 7
    Code-only answers are not considered to be good quality. Please open up and elaborate what this code snippet does. Also if you copied it somewhere, mention the source. Thanks. – quinz Jul 11 '18 at 10:53
  • This is the straight forward answer to the question, Anybody with little bit of larval dusk knowledge will understand it. Anyway it overwrites the download behaviour of chrome for particular session. Here is the reference (https://bugs.chromium.org/p/chromium/issues/detail?id=696481#c61) – Yuvrajsinh Jhala Jul 12 '18 at 05:21
  • Per documentation `Page.setDownloadBehavior` has been marked as deprecated Source: https://chromedevtools.github.io/devtools-protocol/tot/Page/#method-setDownloadBehavior – jdenoc May 12 '22 at 04:22
0

It's not necessary to trigger a separate Guzzle POST, I used a CustomWebDriverCommand instead:

$command = new \Facebook\WebDriver\Remote\CustomWebDriverCommand(
    $driver->getSessionID(),
    "/session/:sessionId/chromium/send_command",
    "POST",
    [
        "cmd" => "Page.setDownloadBehavior",
        "params" => ["behavior" => "allow", "downloadPath" => '/your/download/path']
    ]
);
$driver->getCommandExecutor()->execute($command);
buchi
  • 1
  • 1
  • Welcome to the StackOverflow community. Check the https://stackoverflow.com/help/how-to-ask to improve your question. Hope you will stay with us for a long time :) – Aleksander Ikleiw Jul 17 '20 at 15:13