javascript - node.js 使用 fs writestream 异步下载多个文件
问题描述
在做了第一个没有答案的问题Node.js Javascript 不要从数组中下载图像 (你可以在评论中看到我的第一个代码)我已经解决了我的代码并搜索了其他有我同样问题的人(在这里找到没有答案节点.js 异步下载多个文件)所以我看到他引入了一个下载队列来尝试异步回调,但试图让完成首先下载下一个所以我试图找出可能是什么问题,也许是它程序在启动另一个程序之前是否还没有完成第一个 writestream,所以我尝试了类似file.on("close", function() {
if not with的方法"close"
,至少与"end"
但这只是阻止尝试下载错误的第一个文件。所以我的问题是我在回调中缺少什么?为什么只下载最后一个文件?
const FILEPATH = "mypath/myfolder/"
const HREFSFILENAME = "urls.txt"
var NodeHelper = require("node_helper")
var fs = require("fs");
var http = require('http');
var urls;/*[] = new Array();*/
var url = "";
filename = "";
var regex = /(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?/;
module.exports = NodeHelper.create({
start: function() {
fs.readFile(FILEPATH + HREFSFILENAME, "utf8", function (err,data) {
if (err) return console.log(err);
urls = data.split("\n")
for (i=0; i < urls.length; i++) {
console.log("ROW" + i + ": " + urls[i])
url = urls[i]
if (!url.match(regex)) continue;
filename = FILEPATH + url.substring(url.lastIndexOf('/') + 1)
downloadQueue.addItem(url, filename);
}
/*
for (let i=0; i < urls.length; i++) {
var request = http.get(urls[i], function(response) {
console.log("GET" + i)
var filename = urls[i]
filename = filename.substr(filename.lastIndexOf("/") + 1)
console.log("FILENAME: " + filename)
filename = FILEPATH + filename
var file = fs.createWriteStream(filename);
response.on("end", function() {
file.end();
});
response.pipe(file);
});
}*/
});
},
})
var downloadQueue = {
queue: [],
addItem: function(p_sSrc, p_sDest) {
this.queue.push({
src: p_sSrc,
dest: p_sDest
});
if (this.queue.length === 1) {
this.getNext();
}
},
getNext: function() {
var l_oItem = this.queue[0];
http.get(l_oItem.src, function(response) {
console.log("Downloading: " + l_oItem.dest);
var file = fs.createWriteStream(l_oItem.dest);
response.on("end", function() {
file.end()
console.log("Download complete.");
//file.on("close", function() {
downloadQueue.removeItem();
//});
}).on("error", function(error) {
console.log("Error: " + error.message);
fs.unlink(l_oItem.dest);
});
response.pipe(file);
});
},
removeItem: function() {
this.queue.splice(0, 1);
if (this.queue.length != 0) {
this.getNext();
} else {
console.log("All items downloaded");
}
}
};
我的日志实际上就是这个,你可以看到它只下载最后一张图片
[16:45:51.266] [LOG] ROW0: http://link1/image1.jpg
[16:45:51.271] [LOG] ROW1: http://link2/image2.png
[16:45:51.271] [LOG] ROW2: http://link3/image3.png
[16:45:52.336] [LOG] Downloading: myPath/myfolder/image1.jpg
[18:10:58.456] [LOG] Download complete.
[18:10:58.459] [LOG] Whoops! There was an uncaught exception...
[18:10:58.459] [ERROR] { [Error: ENOENT: no such file or directory, open 'C:\Users\kenzo\myPath\myfolder\image1.jpg
errno: -4058,
code: 'ENOENT',
syscall: 'open',
path:
'C:\\Users\\kenzo\\mypath\\myfolder\\image1.jpg\r' }
[18:10:58.736] [LOG] Downloading: myPath/myfolder/image2.png
[18:10:58.736] [LOG] Download complete.
[18:10:58.737] [LOG] Whoops! There was an uncaught exception...
']8:10:58.737] [ERROR] { [Error: ENOENT: no such file or directory, open 'C:\Users\kenzo\myPath\myfolder\image2.png
errno: -4058,
code: 'ENOENT',
syscall: 'open',
path:
'C:\\Users\\kenzo\\myPath\\myfolder\\image2.png\r' }
[18:10:58.994] [LOG] Downloading: mmyPath/myfolder/image3.png
[18:10:59.026] [LOG] Download complete.
[18:10:59.026] [LOG] All items downloaded
解决方案
看起来像getNext
功能问题,你总是服用queue[0]
getNext: function() {
var l_oItem = this.queue[0];
您可以使用承诺的基础链来解决异步问题。这里readFile
表示异步读取操作。否则使用 async-await 使这个更干净。
// Solution 3.1: Using promise
const promiseReadFile = (name) => {
return new Promise((resolve, _) => {
readFile('promise', name, resolve)
})
}
const p1 = promiseReadFile(files[0])
const p2 = promiseReadFile(files[1])
const p3 = promiseReadFile(files[2])
console.time("PROMISE: TOTAL_TIME")
p1
.then(console.log)
.then(() => p2)
.then(console.log)
.then(() => p3)
.then(console.log)
.then(console.timeEnd.bind(null, "PROMISE: TOTAL_TIME"))
// Solution 3.2: Using promise accumulator
console.time("PROMISE-V2: TOTAL_TIME")
files
.map(promiseReadFile)
.reduce((chain, pr) => {
return chain.then(() => pr)
.then(console.log)
}, Promise.resolve())
.then(console.timeEnd.bind(null, "PROMISE-V2: TOTAL_TIME"))
更多:https ://gist.github.com/deepakshrma/1a899bf49ccb77d3b5be771907b32e4c
推荐阅读
- java - Java离线生成波卡地址
- autohotkey - 由于脚本继续运行,暂停功能无法正常工作
- python - 在 SARIMAX 预测中使用 dynamic =True 和 dynamic = False 时的方法
- python - 内在校准OpenCV后棋盘图案出现矩形
- asp.net - 将 ASP.NET Core 会话状态与多个应用程序实例一起使用
- sql - SUM 最近日期的最新 ID/产品组合
- python - (Synology) 如何使用“ipkg”安装 apache 开发包
- sql - SQL Server 远程连接可从远程 PC localhost 工作,但不能从 Godaddy plesk 主机工作
- reactjs - 如何显示来自打字稿文件的请求
- cairo - 如何将 stb_image 顺序 RGBA 更改为 ARGB?