Next.js API Routes默认不支持XML文件上传,需禁用bodyParser并手动读取raw body;示例中通过config关闭解析、校验Content-Type、流式读取XML字符串并简单验证根节点。

Next.js API Routes默认不支持XML文件上传
Next.js 的 API Routes 默认只解析 application/json、application/x-www-form-urlencoded 和 multipart/form-data(仅限表单字段,不含完整二进制文件)。如果你用 fetch 或 curl 上传一个原始 XML 文件(Content-Type: application/xml),req.body 会是空对象或 undefined —— 因为 Next.js 中间件没启用 raw body 解析。
必须手动读取 raw body 并禁用 bodyParser
要接收 XML 文件,得在 API Route 文件顶部显式关闭内置解析,并用 stream 或 Buffer 手动读取原始请求体。Next.js 13.4+ 支持 config 导出项控制此行为:
export const config = {
api: {
bodyParser: false,
},
};
然后在 handler 中读取:
-
req.method === 'POST'且req.headers['content-type']包含application/xml或text/xml - 用
req.on('data')+req.on('end')累积Buffer,或用stream.Readable转换 - 避免直接调用
JSON.parse(req.body)—— 此时req.body是ReadableStream对象,不是字符串
完整示例:接收并校验 XML 内容
以下是一个能接收原始 XML、检查根节点并返回状态的最小可用路由(pages/api/upload-xml.ts):
export const config = {
api: {
bodyParser: false,
},
};
export default async function handler(req, res) {
if (req.method !== 'POST') {
return res.status(405).json({ error: 'Method not allowed' });
}
const contentType = req.headers['content-type'] || '';
if (!/application\/xml|text\/xml/.test(contentType)) {
return res.status(400).json({ error: 'Expected application/xml or text/xml' });
}
let xmlData = '';
for await (const chunk of req) {
xmlData += chunk.toString();
}
// 简单校验是否为格式良好的 XML(仅示意,生产环境建议用 sax 或 libxmljs)
if (!xmlData.trim().startsWith('
注意:for await (const chunk of req) 是 Node.js 16+ 原生支持的 ReadableStream 迭代方式;若用旧版 Node,需回退到 req.on('data') 事件流。
常见陷阱与绕过方案
上传大 XML 文件时容易触发超时或内存溢出,尤其在 Vercel Serverless 环境中:
- Vercel 默认限制 API Route 最大请求体为
4.5 MB,超过直接 413;需改用middleware+upload到 S3/Cloudflare R2 再异步处理 - XML 解析库如
fast-xml-parser不支持流式解析,全量加载后才校验,可能 OOM;如需校验结构,优先用sax做事件驱动解析 - 不要在 API Route 中写入本地磁盘(
fs.writeFile)—— Vercel 无持久文件系统,写入会失败或丢失 - 若前端用
FormData包裹 XML 文件(如formData.append('file', xmlBlob)),后端收到的是multipart/form-data,需用busboy或formidable解析,而非 raw body 方式
XML 不是 Web 上传的主流格式,多数场景下建议前端先转成 JSON 再提交;若协议强制要求 XML,务必在服务端做 MIME 检查、长度限制和流式预检,否则容易被恶意长标签拖垮进程。










