使用Axios实现服务器间流式传输时内存占用过高的问题及优化咨询
解决Axios服务器间大文件流式传输内存占用过高的问题
常见错误原因
- 未配置
responseType: 'stream':如果downloadContent没设置这个关键配置,Axios会默认将整个响应体读取到内存中,无论文件多大。 - 手动缓存流数据:比如在上传前把下载的流转换成Buffer数组、字符串再传递,这会直接把整个大文件加载进内存。
- 上传时未正确传递流:Axios上传流时,若对
data做了自动转换(比如默认的JSON处理),或者未匹配目标服务器的要求配置headers,会导致流被转成其他格式缓存。
正确实现方案
1. 修正downloadContent函数
必须明确设置responseType: 'stream',让Axios返回可读流而非全量内存数据:
const axios = require('axios'); async function downloadContent(sourceUrl) { const response = await axios.get(sourceUrl, { responseType: 'stream', // 核心配置:返回流式响应 transformResponse: [(data) => data] // 禁用自动转换,确保返回原始流 }); return response.data; // 返回Node.js可读流 }
2. 修正uploadContent函数
直接将下载的可读流作为上传请求的data,避免中间缓存,同时配置合适的headers:
async function uploadContent(targetUrl, readStream) { const response = await axios.post(targetUrl, readStream, { headers: { 'Content-Type': 'application/octet-stream', // 根据目标服务器要求调整类型 // 可选:若能获取文件大小,设置Content-Length可优化传输效率 // 'Content-Length': fileSize }, transformRequest: [(data) => data] // 禁用请求数据自动转换 }); return response.data; }
3. 流式传输调用示例
直接将下载流接入上传流,全程无内存缓存:
async function transferContent(sourceUrl, targetUrl) { const downloadStream = await downloadContent(sourceUrl); await uploadContent(targetUrl, downloadStream); console.log('大文件传输完成'); }
额外优化建议
- 用
stream.pipeline替代直接pipe:Node.js内置的stream.pipeline能更健壮地处理流的错误、自动清理资源,比直接pipe更可靠:
const { pipeline } = require('stream/promises'); async function transferContent(sourceUrl, targetUrl) { const { data: downloadStream } = await axios.get(sourceUrl, { responseType: 'stream' }); const uploadRequest = axios.post(targetUrl, null, { responseType: 'stream', headers: { 'Content-Type': 'application/octet-stream' } }); await pipeline(downloadStream, (await uploadRequest).data); console.log('传输完成'); }
- 调整超时设置:大文件传输耗时久,需设置足够长的超时或禁用超时:
// 在Axios请求配置中添加 timeout: 0, // 禁用超时,或设置如3600000(1小时)的大值
- 监听流错误:避免传输过程中错误未被捕获导致进程异常:
downloadStream.on('error', (err) => { console.error('下载流异常:', err); });
内容的提问来源于stack exchange,提问作者Stefan Stoychev
相关产品推荐
相关产品推荐

