[英]Node FTP download files from one server and upload to another server
我已經尋找了一段時間, 這是我在互聯網上發現的與我的問題有關的唯一資源。 我正在嘗試從一個ftp服務器下載文件,然后使用promises逐個將它們上傳到另一台ftp服務器,而不必在此過程中將文件保存在本地。
首先,我從ftp
模塊遞歸調用client.List()以獲取文件路徑數組,我需要從源ftp服務器下載文件路徑。 這很好。
getRecursively(client, path) {
var _this = this;
let downloadList = [];
let paths = [];
let promise = new Promise((resolve, reject) => {
client.list(path, function(err, list) {
async function loop() {
for (var i = 0; i < list.length; i++) {
if (list[i].type == 'd') {
let _list = await _this.getRecursively(client, path + '/' + list[i].name)
downloadList = downloadList.concat(_list);
} else {
if ( list[i].name.match(/\.(jpg|jpeg)$/i) ) {
downloadList.push({path: path, name: list[i].name});
}
}
}
console.log("One complete");
resolve(downloadList);
}
loop();
})
})
return promise;
}
接下來,我遍歷文件路徑列表並發送使用es6-promise-pool
模塊es6-promise-pool
,因此現在將其並發限制設置為10。
這是每個諾言的樣子:
getAndInsert(file) {
let _this = this;
let promise = new Promise((resolve, reject) => {
let c = new Client();
c.on('ready', () => {
let d = new Client();
d.on('ready', () => {
c.get(file.path + '/' + file.name, function(err, stream) {
if (err) {console.log(err); console.log("FILE NAME: " + file.name)}
d.put(stream.pipe(passThrough()), '/images/' + file.name, function() {
_this.uploadCount += 1;
_this.uploadedImages.push(file.name)
console.log(_this.uploadCount + '/' + _this._list.length + " uploaded.")
c.end();
d.end();
resolve(true);
});
});
})
d.on('error', (err) => {
if (err) console.log(err);
_this.onCompleteCallback();
})
d.connect(destinationFTP);
})
c.on('error', (err) => {
if (err) console.log(err);
_this.onCompleteCallback();
})
c.connect(sourceFTP);
})
return promise;
}
每個Promise都與源和目標ftp服務器建立自己的連接。 當我調用d.put(stream.pipe(passThrough())
時,我d.put(stream.pipe(passThrough())
使用stream
模塊的Transform
對象。
const passThrough = () => {
var passthrough = new Transform();
passthrough._transform = function(data, encoding, done) {
this.push(data);
done();
};
return passthrough;
}
最后,這是釋放承諾的主要代碼。
*buildPromises(list) {
for (let i = 0; i < list.length; i++) {
yield this.getAndInsert(list[i]);
}
}
let iterator = _this.buildPromises(list);
var pool = new PromisePool(iterator, 10);
pool.start()
.then(function(){
console.log("Finished")
}).catch((err) => {
console.log(err);
console.log("error processing pool promise");
})
這將遍歷並構建列表,但是,當我發送承諾時,出現以下錯誤:
Error: write after end
at writeAfterEnd (_stream_writable.js:236:12)
at Transform.Writable.write (_stream_writable.js:287:5)
at Socket.ondata (_stream_readable.js:639:20)
at emitOne (events.js:116:13)
at Socket.emit (events.js:211:7)
at Socket.Readable.read (_stream_readable.js:475:10)
at flow (_stream_readable.js:846:34)
at Transform.<anonymous> (_stream_readable.js:707:7)
at emitNone (events.js:106:13)
它可能會通過5,然后出錯,有時甚至更多,但似乎很一致。 我也注意到有時我會收到類似的錯誤消息,說“文件已在使用中”,但是上傳的每個文件都有一個唯一的名稱。 感謝您的幫助,如果您需要更多信息,我會盡力提供更多信息。 謝謝。
所以我找到了解決方案。 在我的getAndInsert()
函數中正在做:
c.get(file.path + '/' + file.name, function(err, stream) {
if (err) {console.log(err); console.log("FILE NAME: " + file.name)}
d.put(stream.pipe(passThrough()), '/images/' + file.name, function() {
_this.uploadCount += 1;
_this.uploadedImages.push(file.name)
console.log(_this.uploadCount + '/' + _this._list.length + " uploaded.")
c.end();
d.end();
resolve(true);
});
});
問題出在stream.pipe(passThrough())
。 stream
似乎已經結束后,似乎我正在嘗試寫。 這是解決我的問題的原因:
let chunks = [];
stream.on('data', (chunk) => {
chunks.push(chunk);
})
stream.on('end', () => {
d.put(Buffer.concat(chunks), '/images/' + file.name, function() {
_this.uploadCount += 1;
_this.uploadedImages.push(file.name)
console.log(_this.uploadCount + '/' + _this._list.length + " uploaded.")
c.end();
d.end();
resolve(true);
});
})
當從流中獲得新數據時,將數據推送到一個名為chunks
的數組。 流完成后,調用.put
並傳入Buffer.concat(chunks)
希望這可以幫助遇到類似問題的任何人。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.