2017-03-15 65 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); 
     }) 
} 

一直在尋找反饋意見。這個速度沒有我希望的那麼快,所以讓我知道你是否有加速流的想法。