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

Node.js中res.write()传输流数据块无响应问题排查

问题原因与解决方案:res.write()无效且返回false

核心原因

你代码里的致命问题是在ReadableStream的data事件触发前就调用了res.end()。res.end()会立刻终止HTTP响应、关闭连接,后续的res.write()根本没机会把数据发送给客户端。

至于res.write()返回false,这是Node.js的正常机制:当响应缓冲区被写满时,res.write()会返回false,表示当前不能继续写入,需要等待缓冲区排空(触发drain事件)后再继续。但在你的场景里,这个返回值只是次要现象,真正导致数据发不出去的是提前调用了res.end()。

修正方案

有两种可靠的修正方式,推荐第二种更简洁的写法:

方式1:手动管理流事件

修改代码,把res.end()移到文件流的end事件回调里,同时处理缓冲区满的情况:

import { createServer } from 'http'
import { createReadStream } from 'fs'

const server = createServer((req, res) => {
    if (req.method === 'GET' && req.url === '/') {
        res.writeHead(200, { 'Content-Type': 'text/html' })

        const readStream = createReadStream('./src/public/index.html', { encoding: 'utf8' })

        readStream.on('data', (chunk) => {
            console.log(chunk)
            const canWrite = res.write(chunk)
            // 缓冲区满时暂停读取,避免内存溢出
            if (!canWrite) {
                readStream.pause()
                res.once('drain', () => {
                    readStream.resume()
                })
            }
        })

        // 文件流读取完毕后再结束响应
        readStream.on('end', () => {
            res.end()
        })

        // 处理文件读取错误
        readStream.on('error', (err) => {
            res.writeHead(500)
            res.end('服务器错误')
            console.error(err)
        })
    }
})

const PORT = 3000 || 8080

server.listen(PORT, () => { console.log(server.address()) })

方式2:使用pipe()自动管理(推荐)

Node.js的流提供了pipe()方法,可以自动处理流的传输、缓冲区控制和响应结束,代码更简洁不易出错:

import { createServer } from 'http'
import { createReadStream } from 'fs'

const server = createServer((req, res) => {
    if (req.method === 'GET' && req.url === '/') {
        res.writeHead(200, { 'Content-Type': 'text/html' })
        // 直接将文件流管道到响应对象
        createReadStream('./src/public/index.html', { encoding: 'utf8' })
            .pipe(res)
            .on('error', (err) => {
                res.writeHead(500)
                res.end('服务器错误')
                console.error(err)
            })
    }
})

const PORT = 3000 || 8080

server.listen(PORT, () => { console.log(server.address()) })

pipe()会自动帮你做这些事:

  • 当响应缓冲区满时暂停读取文件
  • 缓冲区排空后恢复读取
  • 文件流结束时自动调用res.end()
  • 处理流传输中的错误

内容的提问来源于stack exchange,提问作者anathrax

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 06:06:20