使用 Node JS 下载图像

Downloading image using Node JS

我正在遍历许多图像 uri 以将它们下载到本地。

这是我正在使用的代码:

const optionsImg = {
url: basePath,
   headers: {
       'User-Agent': 'request'
   }
};

let download = function(url, filename, callback) {
   optionsImg.url = url
   request.head(optionsImg, (err, res, body) => {
      console.log('content-type:', res.headers['content-type']);
      console.log('content-length:', res.headers['content-length']);

      request(optionsImg).pipe(fs.createWriteStream(filename)).on('close', callback);
   });
};

但它只会保存列表中的最后一张图像。我怀疑正在发生的事情是它正在尝试异步下载,并且 fs.createWriteStream 一直被中断,直到列表完成。因此只成功下载了最后一张图片。

console.logs 确实显示了不同的内容长度。

如何最好地解决这个问题?提前致谢。

编辑: 这是循环代码:

for (let x = 0; x < pics.length; x++) {
    download(pics[x], localPath + x + '.jpeg', function() {
        console.log('done');
    });
}

request.head 完成时——因为它是一个网络请求,就计算机而言它可能是“永恒”——optionsImg.url 将始终拥有相同的值,因为您保持 re-using 相同 object.

考虑一下:

const obj = { a: undefined };
for(let i = 0; i <= 3; i++) { 
  obj.a = i; 
  setTimeout(console.log, 100, obj);   
}
// will log {a:3} always

您可以通过克隆 object:

来解决上述问题
const obj = { a: undefined };
for(let i = 0; i <= 3; i++) { 
  const obj2 = Object.assign({}, obj);
  obj2.a = i; 
  // or const obj2 = { ...obj, a: i };
  setTimeout(console.log, 100, obj2);   
}
// will log {a:0}, {a:1}, {a:2}, {a:3}

还有一些适用于您的代码:

let download = function(url, filename, callback) {
   const options = {
       ...optionsImg,
       url: url,
   }
   /* alternatively you can do:
   const options = Object.assign({}, optionsImg);
   options.url = url; */
   request.head(options, (err, res, body) => {
      console.log('content-type:', res.headers['content-type']);
      console.log('content-length:', res.headers['content-length']);

      request(options).pipe(fs.createWriteStream(filename)).on('close', callback);
   });
};

Object.assign{...optionsImg} 做一个浅拷贝,所以 headers 仍然是 re-used.

现在每次调用 download() 时,它触发的 request() 调用都会有 'its own' 选项的副本 object.


编辑:对于 OP 中所述的问题,您不需要这个,但是您是否还想复制 headers object——也许您想为每个请求操纵它的值——那么你可以这样做:

const options = {
  ...optionsImg,
  headers: { 
    ...optionsImg.headers,
    // as an example:
    'X-this-is-request-number': `${x} out of ${pics.length}`,
  },
  url: url,
};

您还可以搜索递归 object 克隆实用程序;有很多。