使用 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 克隆实用程序;有很多。
我正在遍历许多图像 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 克隆实用程序;有很多。