你的浏览器无法正常显示内容,请更换或升级浏览器!

NodeJS 文件上传踩坑:大文件超时与内存暴涨

tenfei
tenfei
发布于2026-09-17 10:30 阅读8次
NodeJS 文件上传踩坑:大文件超时与内存暴涨
用 NodeJS 写文件上传接口,小文件一切正常,一传大文件就超时、内存飙升甚至进程崩溃。这篇记录完整的排查和优化过程:从默认的内存缓冲问题、框架体积限制、反向代理超时配置,到改用流式写入的正确姿势,并整理了断点续传和磁盘清理的注意事项,适合做文件服务的开发者参考。
# 一、问题现象 一个文件上传接口,测试环境传几兆的图片没问题,上线后用户传几百兆的视频就出问题:先是**请求超时**,然后**内存占用直线上升**,最后进程被系统杀掉。 # 二、为什么会内存暴涨 很多写法的本质是把整个文件**读进内存再处理**: ```js // 危险写法:整个文件进内存 const chunks = []; req.on("data", c => chunks.push(c)); req.on("end", () => { const buf = Buffer.concat(chunks); // 几百兆直接吃满内存 }); ``` 文件多大就占多大内存,并发几个上传就扛不住了。 # 三、正确做法:流式写入 用管道把请求流直接导向文件写入流,**内存占用恒定**: ```js const fs = require("fs"); const writeStream = fs.createWriteStream(targetPath); req.pipe(writeStream); writeStream.on("finish", () => res.end("ok")); writeStream.on("error", err => { /* 清理临时文件 */ }); ``` 这样不管文件多大,内存里同时只有一小块缓冲区。 # 四、超时问题要分层排查 大文件上传超时,通常**不止一处**配置: | 层级 | 配置项 | 说明 | | --- | --- | --- | | 应用 | server timeout | 框架默认超时往往偏短 | | 反向代理 | 请求体大小限制 | 常见默认仅 1MB | | 反向代理 | 读写超时 | 需按最大文件预估 | | 网关/CDN | 上传时限 | 云端服务也有独立限制 | **逐层放宽才有效**,只改一处经常没用——这是排查时最容易卡住的地方。 # 五、几个必须加的处理 ## 1. 大小限制与类型校验 别等传完再判断,在**请求头阶段**就检查内容长度,超限直接拒绝,省流量也省资源。 ## 2. 失败要清理临时文件 上传中断时,写了一半的文件会残留在磁盘上。务必在错误回调里删除,并加**定时任务清理过期临时文件**。 ## 3. 文件名安全处理 永远不要直接用客户端传来的文件名,要过滤路径穿越字符并重新生成唯一名,否则有**任意文件写入**风险。 ## 4. 进度反馈 大文件上传给用户进度提示体验会好很多,可以基于已接收字节数计算,通过单独接口轮询。 # 六、进阶:断点续传 对超大文件,考虑分片上传: 1. 前端把文件切成固定大小的分片; 2. 每片单独上传,服务端按序号暂存; 3. 全部传完后服务端合并; 4. 支持查询已传分片,中断后从断点继续。 这套方案能显著降低失败重传的成本,具体实现时要注意**分片的并发控制和合并时的磁盘空间**。 # 七、避坑清单 1. **绝不用 Buffer 拼接大文件**,一律走流; 2. **超时配置要全链路检查**,从应用到网关; 3. **失败必清理**,临时文件不清理迟早撑爆磁盘; 4. **文件名必须重命名**,别信客户端输入; 5. **上传目录与代码目录隔离**,避免上传的文件被执行。 # 八、小结 文件上传看起来简单,要做稳得考虑流式处理、超时链路、失败清理和安全校验这几个方面。把这套做扎实,上传功能才算真正可用。

1

0

文章点评
Copyright © from 2021 by namoer.com
458815@qq.com QQ:458815
蜀ICP备2022020274号-2