正在加载,请稍候…

Node.js 流:无内存压力处理大文件

掌握 Node.js 流——转换流、管道 API、背压、服务器发送事件及实际文件处理,实现大文件高效处理。

Node.js 流:无内存压力处理大文件

为什么使用流

将 1GB 文件加载到内存会导致小型服务器崩溃。流以约 64KB 的恒定内存分块处理数据。

Node.js 流:无内存压力处理大文件 插图

文件管道

import { createReadStream, createWriteStream } from 'fs'
import { createGzip } from 'zlib'
import { pipeline } from 'stream/promises'

// 压缩大文件——内存使用恒定
await pipeline(createReadStream('large.csv'), createGzip(), createWriteStream('large.csv.gz'))

Node.js 流:无内存压力处理大文件 插图

转换流

import { Transform } from 'stream'

class UpperCase extends Transform {
  _transform(chunk, _enc, cb) {
    this.push(chunk.toString().toUpperCase())
    cb()
  }
}

Node.js 流:无内存压力处理大文件 插图

HTTP 流式传输

app.get('/export', async (req, res) => {
  res.setHeader('Content-Type', 'application/json')
  res.write('[')
  let first = true
  for await (const doc of db.collection('records').find().stream()) {
    if (!first) res.write(',')
    res.write(JSON.stringify(doc))
    first = false
  }
  res.write(']')
  res.end()
})

服务器发送事件

app.get('/events', (req, res) => {
  res.setHeader('Content-Type', 'text/event-stream')
  const id = setInterval(() => {
    res.write('data: ' + JSON.stringify({ time: Date.now() }) + '\n\n')
  }, 1000)
  req.on('close', () => clearInterval(id))
})

-> 使用 Base64 转换器 对流数据进行编码。