NodeJs 流传输 Error: write EPIPE

场景:

服务端接收到下载请求,根据请求路径拼接文件地址,读取文件流返回给前端

报错:

error Error: write EPIPE

原代码:

本地环境可实现下载

router.get('/download',  
    koaBody(),
    function (ctx, next) {
        const {id,url} = ctx.query
        if (!id || !url ) {
            return ctx.body = {  msg: '请求参数错误' }
        }
        try {
            // let fileObj = downloadZip(id,url)
            ctx.set("Access-Control-Expose-Headers","content-disposition");
            ctx.set(
                "Content-disposition",
                "attachment;filename=" + encodeURIComponent(path.basename(url))
            );
            let filePath = path.resolve(__dirname, "../../"+url); 
            const stream = fs.createReadStream(filePath)
            ctx.body = fileObj.stream; //返回文件流

        } catch(err) {
            ctx.code = 500;
            ctx.body = {
            code: 'error',
            msg: '服务器内部错误'
            };
        }
    }
)

修改后:

ctx.set("Content-Type", "application/zip");

stream.on('error', (err) => {  
    console.error(`Error reading file: ${err}`);  
    ctx.status = 500; // 设置状态码为500(服务器内部错误)  
    ctx.body = { msg: '服务器内部错误' };  
}); 
// 将文件流直接pipe到响应对象,这样Node.js会自动处理数据的传输  
stream.pipe(ctx); 

主要代码:stream.pipe(ctx);

调用pipe方法,这样Node.js会自动处理数据的传输,

注意:在Koa中,通常可以直接使用ctx来pipe流,因为Koa会自动处理它。但在原生node中需要使用ctx.res

完整代码

router.get('/download',  
    koaBody(),
    function (ctx, next) {
        const {id,url} = ctx.query
        if (!id || !url ) {
            return ctx.body = {  msg: '请求参数错误' }
        }
        try {
            // let fileObj = downloadZip(id,url)
            ctx.set("Access-Control-Expose-Headers","content-disposition");
            ctx.set(
                "Content-disposition",
                "attachment;filename=" + encodeURIComponent(path.basename(url))
            );
            ctx.set("Content-Type", "application/zip");  
            let filePath = path.resolve(__dirname, "../../"+url); 
            const stream = fs.createReadStream(filePath)
            stream.on('error', (err) => {  
                console.error(`Error reading file: ${err}`);  
                ctx.status = 500; // 设置状态码为500(服务器内部错误)  
                ctx.body = { msg: '服务器内部错误' };  
            }); 
            // 将文件流直接pipe到响应对象,这样Node.js会自动处理数据的传输  
            stream.pipe(ctx);  
        } catch(err) {
            ctx.code = 500;
            ctx.body = {
            code: 'error',
            msg: '服务器内部错误'
            };
        }
    }
)
### 解决构建客户端和服务端捆绑包时出现的EPIPE错误 当遇到`write EPIPE`错误时,这通常意味着管道写入操作遇到了已经关闭的连接。此问题可能由多种因素引起,包括但不限于网络配置不当、资源耗尽或应用程序逻辑中的异常终止。 对于特定于构建过程中的情况,在处理`build failed with error: write EPIPE`的情况下,可以考虑以下几个方面来排查并解决问题: #### 1. 增加Node.js的最大监听事件数 有时,默认设置下的最大文件描述符数量不足以支持大规模构建任务的需求。可以通过调整环境变量的方式增加这一限制: ```bash ulimit -n 2048 ``` #### 2. 修改Webpack配置以优化打包性能 通过合理配置代码分割策略能够有效减少单次传输的数据量,从而降低发生EPIPE的概率。例如采用如下所示的配置[^3]: ```javascript module.exports = { ... optimization: { splitChunks: { chunks: 'all', }, } }; ``` #### 3. 处理服务端渲染(SSR)场景下document未定义的问题 如果项目涉及服务器端渲染,则可能出现因缺少浏览器环境而导致的对象(如`document`)无法访问的情况。针对这类情形,建议引入条件判断语句确保仅在适当环境中执行相应代码片段[^1]: ```typescript if (typeof window !== 'undefined') { const element = document.getElementById('root'); } ``` #### 4. 清除缓存重新尝试编译 某些情况下旧版本依赖项残留可能会干扰新版本正常工作,因此清理node_modules目录以及清除npm/yarn cache后再安装最新依赖往往能起到意想不到的效果。 #### 5. 更新相关工具链至稳定版 保持所使用的开发工具处于最新的稳定状态有助于规避已知漏洞带来的风险。特别是像Express这样的框架组件,即使存在警告信息也应尽量遵循官方推荐的做法继续推进开发程[^2]。 以上措施综合运用可以帮助缓解乃至彻底消除构建过程中遭遇的EPIPE错误现象。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值