Node.js WriteStream finish事件提前触发,大文件写入不完整怎么解决?
Node.js 大文件截取:确保完整写入后再返回函数
我需要在Node.js中移除一个大文件的前若干字节,并将剩余内容写入新文件。我的做法是创建一个带偏移量的ReadStream,再通过pipe将其导入到新文件的WriteStream中,代码如下:
const inputStream = createReadStream(inputPath, { start: NUM_BYTES_OFFSET, }); const outputStream = createWriteStream(outputPath); inputStream.pipe(outputStream); await new Promise((resolve) => outputStream.on("finish", resolve)); return;
但监听inputStream的data事件时发现,finish事件触发、promise解析并返回函数前,仅写入了0或1个数据块,最终得到的输出文件体积很小。请问如何确保全部文件内容写入输出目标后再让函数返回?
问题原因与解决办法
你的代码只监听了写入流的finish事件,却没处理读取流的异常,也没覆盖流的完整生命周期,这会导致读取流中途出错时,写入流提前触发finish,但实际数据还没写完。以下是修正方案:
修正后的完整代码
const { createReadStream, createWriteStream } = require('fs'); async function truncateLargeFile(inputPath, outputPath, NUM_BYTES_OFFSET) { return new Promise((resolve, reject) => { const inputStream = createReadStream(inputPath, { start: NUM_BYTES_OFFSET }); const outputStream = createWriteStream(outputPath); // 处理读取流错误,避免异常导致流中断却未捕获 inputStream.on('error', (err) => { outputStream.destroy(); // 销毁写入流,防止残留不完整数据 reject(err); }); // 处理写入流错误,比如磁盘满、权限问题 outputStream.on('error', (err) => { inputStream.destroy(); // 终止读取流,避免无效读取 reject(err); }); // 所有数据写入完成后触发finish,此时才resolve outputStream.on('finish', resolve); inputStream.pipe(outputStream); }); }
核心要点
- 必须监听双流错误:读取流或写入流任何一方出错,都会导致数据传输中断,如果不捕获这些错误,Promise要么一直pending,要么提前resolve但文件不完整。
finish事件的可靠性:Node.js中写入流的finish事件确实是在所有数据都写入底层系统后才触发,但前提是读取流正常结束且没有异常。- 流的销毁机制:当某一流出错时,销毁另一流可以避免资源浪费和无效操作,同时保证文件状态的一致性。
内容的提问来源于stack exchange,提问作者Rayhan Memon
相关产品推荐
相关产品推荐

