繁体   English   中英

如何通过 ssh2 Node.js 模块(在 Electron 应用程序中)使用 SFTP 一次下载/上传多个文件?

[英]How can I download/upload multiple files at once using SFTP through the ssh2 Node.js module (within an Electron app)?

我正在使用 Electron 构建一个简单的 SFTP 客户端,我正在尝试使用 ssh2 模块和该模块中的 SFTPStream 一次下载或上传多个文件。 我尝试了许多不同的方法结构,其中一些包括使用 es6-promise-pool。 我所做的每一次尝试都会导致要传输的文件数组中的一个文件被正确传输,然后是随后的

MaxListenersExceededWarning:检测到可能的 EventEmitter 内存泄漏。 11 个 sftp_message 侦听器添加到 [EventEmitter]。 使用emitter.setMaxListeners() 增加限制

消息显示在控制台中,其余文件不会传输。 我不确定如何更改我的方法结构以防止这种情况发生。 我正在使用 ipcRenderer 告诉 ipcMain 执行我将在此处显示的方法(例如,这是我上传文件的结构)。

let counter = 0;

// Upload local file to server
ipcMain.on('upload_local_files', (event, args) => { // args[0] is connection settings, args[1] is array of file paths
  let conn = new Client();
  conn.on('ready', () => {
    let pool = new PromisePool(uploadFileProducer(conn, args[1]), 10);
    pool.start().then(() => {
      conn.end();
      counter = 0;
      let tempArgs = [];
      tempArgs.push(curLocalDir);
      tempArgs.push(curRemoteDir);
      event.sender.send('local_upload_complete', tempArgs);
    });
  }).connect(args[0]);
});

// Producer used in promise pool to upload files
function uploadFileProducer(conn, files){
  if(counter < 100 && counter < files.length){
    counter++;
    return(uploadFile(conn, files[counter - 1]));
  }else{
    return null;
  }
}

// Function used to upload files in promise pool
function uploadFile(conn, file){
  return new Promise((resolve, reject) => {
    conn.sftp((error, sftp) => {
      return sftp.fastPut(file, curRemoteDir + file.substring(file.lastIndexOf('/') + 1), {}, (error) => {
        resolve(file);
      });
    });
  });
}

诚然,promise 池的使用对我来说是新的,我不确定我是否打算正确使用它们。 关于此主题的另一篇文章使用承诺池来防止我遇到的问题发生,但该示例不涉及 Electron 应用程序(我不知道这是否相关)。 我很感激我能得到的任何帮助!

问题不在于Warning ,它只是一个警告,在您当前的用例中是正常的。 上传的问题是PromisePool的错误使用。

我假设您正在使用es6-promise-pool

您应该将promise生产者函数传递给构造函数,但您正在调用该函数并传递一个promise,这就是为什么只上传单个文件的原因。

您应该在不调用它的情况下传递生产者,或者制作一个返回函数的生产者,或者使用生成器。

PromisePool 构造函数接受一个 Promise 生成函数作为它的第一个参数。

function *uploadFileProducer(conn, files) {
    for(const file of files)
        yield uploadFile(conn, file);
}

现在你可以调用:

let pool = new PromisePool(uploadFileProducer(conn, args[1]), 10)

PromisePool会正确迭代生成器函数返回的迭代器,并相应地处理并发。

您还可以创建一个函数,每次调用都会返回一个Promise

function uploadFileProducer(conn, files) {
  files = files.slice(); // don't want to mutate the original
  return () => uploadFile(conn, files.shift())
}

关于警告,如果您同时上传多个内容是正常的,如果是这种情况,您可以使用以下方法增加限制:

emitter.setMaxListeners(n)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM