使用 Node JS 下载图像

时间:2021-06-18 11:39:12

标签: javascript node.js fs

我正在遍历许多图像 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');
    });
}

1 个答案:

答案 0 :(得分:2)

request.head 完成时——因为它是一个网络请求,就计算机而言它也可能是“永恒”——将始终具有相同的值因为你不断重复使用同一个对象。

考虑一下:

optionsImg.url

您可以通过克隆对象来解决上述问题:

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

有些适用于您的代码:

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 并且它触发的 download() 调用都将拥有选项对象的“自己的”副本。


编辑:对于 OP 中所述的问题,您不需要这个,但如果您还想复制标头对象 - 也许您想为每个请求操作其值 - 那么您可以这样做:

request()

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

相关问题