NextJS API路由流式传输大文件遇4MB限制报错(Vercel生产环境)
解决Vercel生产环境Next.js API路由大文件流式传输4MB限制问题
问题根源
你碰到的4MB限制不是Next.js配置的问题,而是Vercel部署API路由时,默认会将其托管在AWS Lambda上——Lambda本身对同步响应的payload大小限制就是4MB。你之前设置的responseLimit和bodyParser.sizeLimit是控制请求的大小,和响应限制完全无关,所以不管怎么调都没用。
可行解决方案
方案1:直接重定向到原始文件URL(最简单高效)
既然已经拿到了original_file_url,完全没必要通过API路由中转,直接返回302重定向,让客户端直接请求原始文件,彻底绕过Lambda的响应限制:
const handler = async (req, res) => { if (req.method.toUpperCase() !== 'GET') return res.status(405).json({ error: 'Method Not Allowed' }); const content_id = req.query.id; const file = await myDataBase.getFile(content_id); const { original_file_url } = file.meta; // 重定向到原始文件地址 res.writeHead(302, { Location: original_file_url }); res.end(); }; export const config = { api: { bodyParser: false, // 禁用bodyParser,提升性能 }, }; export default handler;
方案2:正确配置流式响应(需中转场景)
如果必须通过API路由中转(比如需要鉴权),要确保Lambda以流式方式发送响应,而非缓存整个payload。修改代码如下:
import { pipeline } from 'stream/promises'; import got from 'got'; const handler = async (req, res) => { if (req.method.toUpperCase() !== 'GET') return res.status(405).json({ error: 'Method Not Allowed' }); const content_id = req.query.id; const file = await myDataBase.getFile(content_id); const { original_file_url, original_filename } = file.meta; try { // 设置流式响应头 res.setHeader('Content-Disposition', `attachment; filename="${original_filename}"`); res.setHeader('Transfer-Encoding', 'chunked'); res.setHeader('Cache-Control', 'no-cache'); // 使用stream.pipeline替代直接pipe,错误处理更可靠 const stream = got.stream(original_file_url); await pipeline(stream, res); } catch (error) { res.status(500).end('Failed to fetch file'); } }; export const config = { api: { bodyParser: false, // 必须禁用bodyParser responseLimit: false, // 取消请求大小限制 externalResolver: true, // 告诉Next.js路由用外部流式处理 }, }; export default handler;
关键配置说明
bodyParser: false:禁用自动请求体解析,减少不必要的内存占用responseLimit: false:取消Next.js对请求大小的限制externalResolver: true:告知Next.js无需等待handler执行完毕,直接处理流式响应Transfer-Encoding: chunked:明确要求服务器用分块传输,避免Lambda缓存整个响应
内容的提问来源于stack exchange,提问作者Caleb Taylor
相关产品推荐
相关产品推荐

