0

我通过 ssh2-sftp-client 通过 readStream 上传文件。这很好,但是当我添加一个事件侦听器时,文件没有完全上传:

这有效:

const stream = fs.createReadStream(myFile);
return this.sftpClient.put(stream, remoteFilePath)

这只会上传文件的 80%

const stream = fs.createReadStream(myFile);
stream.on('data', (chunk) => {
  console.log('chunk passed');
});
return this.sftpClient.put(stream, remoteFilePath)

调试模式下的最后一条消息显示没有错误:

chunk passed
Outbound: Sending CHANNEL_DATA (r:0, 9380)
SFTP: Outbound: Sent WRITE (id:1554)
Inbound: CHANNEL_DATA (r:0, 28)
SFTP: Inbound: Received STATUS (id:1554, 0, "Success")
Outbound: Sending CHANNEL_DATA (r:0, 17)
SFTP: Outbound: Buffered CLOSE
Inbound: CHANNEL_DATA (r:0, 28)
SFTP: Inbound: Received STATUS (id:1555, 0, "Success")
CLIENT[sftp]: put: promise resolved
CLIENT[sftp]: put: Removing temp event listeners

管道流时同样的问题:

const stream = fs.createReadStream(myFile);
const fileMd5Hash = crypto.createHash('md5').setEncoding('hex');
stream.pipe(fileMd5Hash);
return this.sftpClient.put(stream, remoteFilePath)

问题似乎在于 onData 事件和 pipe() 都将流切换到流动模式,这可能会导致数据丢失,因为数据会立即“尽快”传递给应用程序。所以我想知道:如何在不将读取流切换到流动模式的情况下读取块以从整个文件创建我的 md5sum 哈希?

4

1 回答 1

0

所以我现在知道会发生什么:我在示例中跳过了我认为不相关的一行:

const stream = fs.createReadStream(myFile);

createDirsIfNotExist(remoteFilePath);

return this.sftpClient.put(stream, remoteFilePath)

所以我有:

const stream = fs.createReadStream(myFile);

stream.on('data', (chunk) => {
  console.log('chunk passed');
});

createDirsIfNotExist(remoteFilePath);

return this.sftpClient.put(stream, remoteFilePath)

问题是 stream.on('data'...) 立即触发切换到流动模式。如果 createDirsIfNotExist 需要一些时间,则第一个块将不会在 sftpClient 中通过管道传输。

如果我换行:


createDirsIfNotExist(remoteFilePath);

stream.on('data', (chunk) => {
  console.log('chunk passed');
});

return this.sftpClient.put(stream, remoteFilePath)

它按预期工作。为了确保我将数据事件处理程序包装在恢复事件处理程序中:

let listening = false;
stream.on('resume', () => {
  if(!listening) {
    stream.on('data', (chunk) => {
      console.log('chunk passed');
      // do whatever else is needed
    });
    listening = true;
});

这避免了计时问题,但看起来很奇怪。

于 2022-02-07T08:15:59.610 回答