You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 08:32:16