Next.js API Route中await request.formData()卡顿问题排查
问题描述
接口执行时卡在console.log("0")之后,await request.formData()无法完成,代码如下:
export async function POST(request: Request) { try { const balance = await UserHasBalance(); console.log("0"); const formData = await request.formData(); console.log("1"); // 卡在"0"处 } catch (err) { // 建议补充错误捕获,排查具体报错 console.error(err); } }
提交的multipart/form-data表单包含一个字符串字段url,以及一个从localStorage取出的PDF base64字符串(原文件100KB,base64后约133KB,整体请求Content-Length为155033):
------WebKitFormBoundaryRV59K1PqB5ZoUDBk Content-Disposition: form-data; name="url" dsfd.com ------WebKitFormBoundaryRV59K1PqB5ZoUDBk Content-Disposition: form-data; name="file" data:application/pdf;base64,JVBERi0xLjQKJdPr6eEKMSAwIG9iago8PC9DcmVhdG9yIChDaHJvbWl1bSkKL1Byb2R1Y2VyIChTa2lhL1BERiBtMTE2KQovQ3JlYXRpb25EYXRlIChEOjIwMjMxMDA2MDcyMDE3KzAwJzAwJykKL01vZERhdGUgKEQ6MjAyMzEwMDYwNzIwMTcrMDAnMDAnKT4+CmVuZG9iagozIDAgb2Jq....huge string
请求头信息:
Accept: application/json, text/plain, */* Accept-Encoding: gzip, deflate, br, zstd Content-Length: 155033 Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryRV59K1PqB5ZoUDBk
关键现象
- 此前表单使用字符串+File对象格式时,接口可正常工作
- 当base64字符串缩减至15KB时,接口恢复正常
- 未配置显式请求大小限制,请求由Axios发送,希望避免使用外部存储工具
解决方案
1. 排查框架默认解析限制
多数后端框架对multipart/form-data解析有隐式大小限制,即使未显式配置:
- Next.js App Router:在
next.config.js中显式设置serverBodySizeLimit测试module.exports = { serverBodySizeLimit: '5mb', } - Express:检查
multer或body-parser的limits配置,放开字段大小限制const multer = require('multer'); const upload = multer({ limits: { fieldSize: 5 * 1024 * 1024 } }); // 5MB字段限制
2. 将base64转为Blob构造FormData
把localStorage中的base64转为Blob(模拟File对象),还原到之前正常工作的表单格式:
// 前端Axios请求代码修改 const base64Str = localStorage.getItem('pdfBase64'); const base64Data = base64Str.replace('data:application/pdf;base64,', ''); const buffer = Uint8Array.from(atob(base64Data), c => c.charCodeAt(0)); const blob = new Blob([buffer], { type: 'application/pdf' }); const formData = new FormData(); formData.append('url', 'dsfd.com'); formData.append('file', blob, 'document.pdf'); axios.post('/api/your-endpoint', formData, { headers: { 'Content-Type': 'multipart/form-data' } });
后端解析时处理的是文件流而非大字符串,和之前的正常场景一致,可规避字符串解析的内存限制。
3. 后端直接读取原始请求流解析
绕过request.formData(),手动解析请求流,精准控制大小限制:
import { parseMultipartFormData } from 'next/dist/server/api-utils/node'; // Next.js示例,其他框架用对应解析库 export async function POST(request: Request) { try { const balance = await UserHasBalance(); console.log("0"); const formData = await parseMultipartFormData(request, { maxFileSize: 5 * 1024 * 1024, maxFieldSize: 5 * 1024 * 1024 }); console.log("1"); // 后续业务逻辑 } catch (err) { console.error('解析错误:', err); } }
4. 配置Axios请求参数
显式设置Axios的内容长度限制,排除客户端配置异常:
axios.post('/api/your-endpoint', formData, { maxContentLength: 5 * 1024 * 1024, maxBodyLength: 5 * 1024 * 1024, headers: { 'Content-Type': 'multipart/form-data' } });
内容的提问来源于stack exchange,提问作者Shivam Anand
相关产品推荐
相关产品推荐

