在 NodeJS 中侦听 createReadStream 上的 'data' 事件时,写入 createWriteStream 的文件被损坏
File written to createWriteStream gets corrupted when listening to 'data' event on createReadStream in NodeJS
我有一个 Electron 应用程序,我编写了一个服务来使用 Node 的 fs
模块复制文件。当不监听 fs.createReadStream
的 data
事件时,文件复制工作正常,但是当我添加 readStream.on('data', ...
事件时,输出文件被损坏(输出文件的大小总是小于原始文件)。这是我复制文件的功能代码:
copyFile(sourcePath: string, targetPath: string): Observable<FileCopyResponseModel> {
const copyResponse = new Subject<FileCopyResponseModel>();
const fileSize = this.node.fs.statSync(sourcePath).size;
const readStream = this.node.fs.createReadStream(sourcePath);
let bytesCopied = 0;
readStream.once("error", (err) => {
const response = new FileCopyResponseModel();
response.is_error = true;
response.error = err;
copyResponse.next(response);
});
readStream.on('data', (buffer) => {
bytesCopied+= buffer.length
const response = new FileCopyResponseModel();
response.is_error = false;
response.is_done = false;
response.size = fileSize;
response.size_copied = bytesCopied;
copyResponse.next(response);
});
this.node.mkdirp(this.node.path.dirname(targetPath), (err) => {
if (err) {
const response = new FileCopyResponseModel();
response.is_error = true;
response.error = err;
copyResponse.next(response);
} else {
const writeStream = this.node.fs.createWriteStream(targetPath);
writeStream.once("error", (err) => {
const response = new FileCopyResponseModel();
response.is_error = true;
response.error = err;
copyResponse.next(response);
});
writeStream.once("close", (ex) => {
const response = new FileCopyResponseModel();
response.is_error = false;
response.is_done = true;
response.size = fileSize;
copyResponse.next(response);
});
readStream.pipe(writeStream);
}
});
return copyResponse;
}
如果我只是注释掉这部分代码,文件就会被正确复制:
readStream.on('data', (buffer) => {
bytesCopied+= buffer.length
const response = new FileCopyResponseModel();
response.is_error = false;
response.is_done = false;
response.size = fileSize;
response.size_copied = bytesCopied;
copyResponse.next(response);
});
知道这里出了什么问题吗?
在旁注中,在侦听 data
事件时正确报告复制进度。
我认为您正在尝试两次使用可读流。一次在 on('data',
处理程序中,一次在 readStream.pipe(writeStream);
中。 on('data',
将消耗可读流,然后才能将其通过管道传输到写入流。
您可以尝试替换以下行:
readStream.pipe(writeStream);
和
readStream.on('data', (buffer) => {
bytesCopied+= buffer.length
const response = new FileCopyResponseModel();
response.is_error = false;
response.is_done = false;
response.size = fileSize;
response.size_copied = bytesCopied;
copyResponse.next(response);
// new bit
writeStream.write(buffer);
});
并从上面的处理程序中删除 on('data,
。
您也可以在读取流结束时结束写入流。
readStream.on('end', function() {
console.log('end');
writeStream.end();
});
我有一个 Electron 应用程序,我编写了一个服务来使用 Node 的 fs
模块复制文件。当不监听 fs.createReadStream
的 data
事件时,文件复制工作正常,但是当我添加 readStream.on('data', ...
事件时,输出文件被损坏(输出文件的大小总是小于原始文件)。这是我复制文件的功能代码:
copyFile(sourcePath: string, targetPath: string): Observable<FileCopyResponseModel> {
const copyResponse = new Subject<FileCopyResponseModel>();
const fileSize = this.node.fs.statSync(sourcePath).size;
const readStream = this.node.fs.createReadStream(sourcePath);
let bytesCopied = 0;
readStream.once("error", (err) => {
const response = new FileCopyResponseModel();
response.is_error = true;
response.error = err;
copyResponse.next(response);
});
readStream.on('data', (buffer) => {
bytesCopied+= buffer.length
const response = new FileCopyResponseModel();
response.is_error = false;
response.is_done = false;
response.size = fileSize;
response.size_copied = bytesCopied;
copyResponse.next(response);
});
this.node.mkdirp(this.node.path.dirname(targetPath), (err) => {
if (err) {
const response = new FileCopyResponseModel();
response.is_error = true;
response.error = err;
copyResponse.next(response);
} else {
const writeStream = this.node.fs.createWriteStream(targetPath);
writeStream.once("error", (err) => {
const response = new FileCopyResponseModel();
response.is_error = true;
response.error = err;
copyResponse.next(response);
});
writeStream.once("close", (ex) => {
const response = new FileCopyResponseModel();
response.is_error = false;
response.is_done = true;
response.size = fileSize;
copyResponse.next(response);
});
readStream.pipe(writeStream);
}
});
return copyResponse;
}
如果我只是注释掉这部分代码,文件就会被正确复制:
readStream.on('data', (buffer) => {
bytesCopied+= buffer.length
const response = new FileCopyResponseModel();
response.is_error = false;
response.is_done = false;
response.size = fileSize;
response.size_copied = bytesCopied;
copyResponse.next(response);
});
知道这里出了什么问题吗?
在旁注中,在侦听 data
事件时正确报告复制进度。
我认为您正在尝试两次使用可读流。一次在 on('data',
处理程序中,一次在 readStream.pipe(writeStream);
中。 on('data',
将消耗可读流,然后才能将其通过管道传输到写入流。
您可以尝试替换以下行:
readStream.pipe(writeStream);
和
readStream.on('data', (buffer) => {
bytesCopied+= buffer.length
const response = new FileCopyResponseModel();
response.is_error = false;
response.is_done = false;
response.size = fileSize;
response.size_copied = bytesCopied;
copyResponse.next(response);
// new bit
writeStream.write(buffer);
});
并从上面的处理程序中删除 on('data,
。
您也可以在读取流结束时结束写入流。
readStream.on('end', function() {
console.log('end');
writeStream.end();
});