2017-03-15 77 views
0

所以我创建一个类,最终想创建一个方法,该方法需要在SFTP服务器上的文件,并产生可以管道到其他流/函数的读取流。我大部分的方式,除了我的readStream行为奇怪。下面是相关的代码:节点异步从SFTP连接的读取流

const Client = require('ssh2').Client, 
     Readable = require('stream').Readable, 
     async = require('async'); 

/** 
* Class Definition stuff 
* ...... 
*/ 

getStream(get) { 
    const self = this; 
    const rs = new Readable; 
    rs._read = function() { 
     const read = this; 
     self.conn.on('ready', function(){ 
      self.conn.sftp(function(err,sftp) { 
       if(err) return err; 

       sftp.open(get, 'r', function(err, fd){ 
        sftp.fstat(fd, function(err, stats) { 

         let bufferSize = stats.size, 
          chunkSize = 512,//bytes 
          buffer = new Buffer(bufferSize), 
          bytesRead = 0; 

         async.whilst(
          function() { 
           return bytesRead < bufferSize; 
          }, 
          function (done) { 
           sftp.read(fd, buffer, bytesRead, chunkSize, bytesRead, 
           function (err, bytes, buff) { 
            if (err) return done(err); 
            // console.log(buff.toString('utf8')); 
            read.push(buff); 
            bytesRead += bytes; 
            done(); 
           }); 
          }, 
          function (err) { 
           if (err) console.log(err); 
           read.push(null); 
           sftp.close(fd); 
          } 
         ); 

        }); 
       }); 
      }); 
     }).connect(self.connectionObj); 
    } 
    return rs; 

} 

在其他地方,我会调用这个方法就像这样:

let sftp = new SFTP(credentials); 

sftp.getStream('/path/file.csv') 
.pipe(toStuff); 
.pipe(toOutput); 

所以,长话短说。在SFTP.read操作期间,read.push(buff)一直重复推送相同的文件第一部分。但是,当我console.log(buff)正确流式传输整个文件?

所以我很想知道我在做什么错误的读取流,它只是推动文件的开始,而不是继续到缓冲区的下一部分。

这里的SSH2 SFTP客户端上的文档:https://github.com/mscdex/ssh2-streams/blob/master/SFTPStream.md

我用这太问题为灵感就是我上面写道:node.js fs.read() example

这类似于/相关:Reading file from SFTP server using Node.js and SSH2

回答

0

好,经过很多麻烦,我意识到我犯了一些错误。首先,每当流准备读取更多数据时调用_read函数,这意味着每次调用_read时都会启动SFTP连接。这也意味着每次都会启动sftp.read()函数,将起始点重新设置为开始。

我需要一种方法来首先设置连接,然后读取和流式传输文件数据,因此我选择了库noms。以下是最终的代码,如果有人感兴趣:

getStream (get) { 
    const self = this; 

    let connection, 
     fileData, 
     buffer, 
     totalBytes = 0, 
     bytesRead = 0; 

    return nom(
     // _read function 
     function(size, next) { 
      const read = this; 

      // Check if we're done reading 
      if(bytesRead === totalBytes) { 
       connection.close(fileData); 
       connection.end(); 
       self.conn.end(); 
       console.log('done'); 
       return read.push(null); 
      } 

      // Make sure we read the last bit of the file 
      if ((bytesRead + size) > totalBytes) { 
       size = (totalBytes - bytesRead); 
      } 

      // Read each chunk of the file 
      connection.read(fileData, buffer, bytesRead, size, bytesRead, 
       function (err, byteCount, buff, pos) { 
        // console.log(buff.toString('utf8')); 
        // console.log('reading'); 
        bytesRead += byteCount; 
        read.push(buff); 
        next(); 
       } 
      ); 
     }, 
     // Before Function 
     function(start) { 
      // setup the connection BEFORE we start _read 
      self.conn.on('ready', function(){ 
       self.conn.sftp(function(err,sftp) { 
        if(err) return err; 
        sftp.open(get, 'r', function(err, fd){ 
         sftp.fstat(fd, function(err, stats) { 
          connection = sftp; 
          fileData = fd; 
          totalBytes = stats.size; 
          buffer = new Buffer(totalBytes); 
          console.log('made connection'); 
          start(); 
         }); 
        }); 
       }); 
      }).connect(self.connectionObj); 
     }) 
} 

一直在寻找反馈意见。这个速度没有我希望的那么快,所以让我知道你是否有加速流的想法。