如何通过Next.js路由处理器将ReadableStream流式转发至后端REST API
Next.js 流式文件上传中转方案
问题描述
我有一个Next.js文件上传应用,客户端配备简单表单和上传组件,希望将文件以ReadableStream形式从客户端发送至Next.js的Route Handler,再通过REST API转发到后端服务,全程使用fetch。目前能看到客户端到Node中间件的POST数据是可读流,但不知道如何在不将文件存储到Next.js服务器内存或磁盘的前提下转发至后端,理想状态是直接将流pipe到后端,试过pipeTo但无法整合实现,不确定该功能是否可行。补充要求:必须通过中间件转发,不能使用预签名URL等方式,要直接将可读流通过另一个fetch请求发往后端。
实现方案
这个需求完全可行,核心是直接传递流而不解析存储,以下是具体代码实现:
1. 客户端上传代码
直接使用FormData提交文件,浏览器会自动以流式方式发送请求,无需额外处理:
// 客户端上传组件 export default function UploadForm() { const handleSubmit = async (e) => { e.preventDefault(); const formData = new FormData(e.target); // 直接发送FormData,浏览器自动流式传输 const res = await fetch('/api/upload', { method: 'POST', body: formData, }); res.ok ? console.log('上传完成') : console.error('上传失败'); }; return ( <form onSubmit={handleSubmit}> <input type="file" name="file" required /> <button type="submit">开始上传</button> </form> ); }
2. Next.js Route Handler 中转代码
在Route Handler中直接获取请求的body流,作为转发请求的body,全程不落地存储:
// app/api/upload/route.js export async function POST(request) { // 直接拿到客户端传来的可读流,不要调用request.formData()(会把文件读进内存) const stream = request.body; // 转发到后端服务 const backendRes = await fetch('https://你的后端API地址/upload', { method: 'POST', headers: { // 按需转发必要的请求头,比如认证信息 Authorization: request.headers.get('Authorization'), // 不要转发Content-Length,流式传输无法提前确定长度 }, body: stream, duplex: 'half' // Node.js环境下必须配置,否则流式body会报错 }); // 将后端的响应原封不动返回给客户端 return new Response(backendRes.body, { status: backendRes.status, headers: backendRes.headers }); }
关键注意事项
- 不要解析FormData:如果在Route Handler中调用
await request.formData(),会把整个文件读取到内存中,失去流式传输的意义,直接用request.body获取流即可。 - duplex配置:Node.js环境下使用
fetch发送流式body时,必须指定duplex: 'half',这是Node.js fetch API的要求,否则会抛出错误。 - ** header处理**:不要转发
Content-Length头,因为流式传输时无法提前知道文件总大小,后端服务会自动处理chunked编码的请求。
内容的提问来源于stack exchange,提问作者Hob
相关产品推荐
相关产品推荐

