簡體   English   中英

節點FTP從一台服務器下載文件並上傳到另一台服務器

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM