-5

Let's say I want to save an image to disk.

var path = require('path');
var webdriver = require("selenium-webdriver");
var chrome = require('selenium-webdriver/chrome');
var By = webdriver.By;
var until = webdriver.until
const fs = require("fs");
var o = new chrome.Options();
o.addArguments("--disable-web-security");
var browser = new webdriver.Builder().forBrowser('chrome').setChromeOptions(o).build();

fetch("https://upload.wikimedia.org/wikipedia/commons/9/9d/Blue_Flower.png");

This doesn't work, fetch is not defined.

I then tried adding fetch into browser.executeScript

var promise1 = browser.executeScript(`return fetch("https://upload.wikimedia.org/wikipedia/commons/9/9d/Blue_Flower.png");`)
promise1.then((x) => x.arrayBuffer()).then((buffer) => fs.writeFile("flower.png", buffer, () => console.log("done")))

This doesn't work. It turns out that when executeScript returns an object, all functions in the object are replaced with {}.

I then tried returning the buffer from executeScript.

var promise1 = browser.executeScript(`return fetch("https://upload.wikimedia.org/wikipedia/commons/9/9d/Blue_Flower.png").then((x) => x.arrayBuffer());`)
promise1.then((buffer) => fs.writeFile("flower.png", buffer, () => console.log("done")))

Still doesn't work. It turns out that buffer becomes {};

Is there some way I can access the arrayBuffer without it turning into {} after it comes out of executeScript?

David Lui
  • 110
  • 4
  • Does this answer your question? [How to download a file with Node.js (without using third-party libraries)?](https://stackoverflow.com/questions/11944932/how-to-download-a-file-with-node-js-without-using-third-party-libraries) – esqew Nov 03 '21 at 01:26
  • Is it something you want to use selenium for? If not, To simply download a file, you can use axios with fs.createWriteStream(). – user212942 Nov 03 '21 at 01:30
  • Nodejs does not contain `fetch()`. You can either use the module node-fetch, write code using the http module to make the http request yourself and collect the response or you can use any one of the other excellent alternatives [here](https://github.com/request/request/issues/3143). My personal favorite is [`got()`](https://www.npmjs.com/package/got) because I like it's interface and flexibility and you can stream it's response directly to a file (minimizing memory usage). – jfriend00 Nov 03 '21 at 02:34

2 Answers2

0
const res = await fetch(url);
const fileWriteStream = fs.createWriteStream('/directory/path.ext');
res.body.pipe(fileWriteStream);
Vishnu
  • 11,614
  • 6
  • 51
  • 90
0

I managed to do it by using base64. I used code from this answer :

var promise1 = browser.executeScript(`return fetch("https://upload.wikimedia.org/wikipedia/commons/9/9d/Blue_Flower.png").then((x) => x.arrayBuffer()).then(function(buffer){
    var blob = new Blob([buffer])

var reader = new FileReader();
reader.readAsDataURL(blob);
    
    return reader
}).then(function(reader){
    return new Promise(function(x, y){
        this.addEventListener("loadend", function(){
            x(this);
        }.bind(this))
    }.bind(reader)); 
}).then(function(reader){
    return reader.result.slice(reader.result.indexOf(",")+1);
})  
`)
promise1.then(function(b64data){
    let buff = Buffer.from(b64data, 'base64');
    fs.writeFileSync("flower.png", buff);
    console.log("done");
})
David Lui
  • 110
  • 4