express需用express.raw({type:['application/xml','text/xml']})捕获xml原始流,req.body为buffer,须tostring()后交xml2js.parsestring()解析,注意编码、命名空间及大文件流式处理。

Express里怎么接收到XML文件流
Express默认不解析XML,req.body 对XML请求是空的,除非你手动挂载解析中间件。别指望express.json()或express.urlencoded()能处理它——它们只认application/json和application/x-www-form-urlencoded。
真实场景中,客户端常以application/xml或text/xml发POST请求(比如SOAP调用、第三方系统回调),这时必须靠raw中间件捕获原始字节流:
- 用
express.raw({ type: ['application/xml', 'text/xml'] }),确保req.body是Buffer - 顺序很重要:必须放在路由前、其他body解析中间件之后(避免被提前消费)
- 如果同时支持JSON和XML,得分开写两套
raw,不能合并type通配——express.json()会吃掉所有req.body,导致后续raw拿不到数据
用xml2js解析Buffer时为什么报“Cannot read property 'length' of undefined”
这是最常见报错,根本原因是没等req.body完整就传给了xml2js.parseString()。Express的raw中间件确实把整个请求体转成Buffer了,但如果你在req.on('data')里手动拼接、又没处理req.on('end'),或者误用了req.pipe(),req.body就会是undefined。
正确做法只有一条:信任express.raw,直接用req.body:
app.post('/api/data', express.raw({ type: 'application/xml' }), (req, res) => {
if (!req.body || req.body.length === 0) {
return res.status(400).send('Empty XML');
}
xml2js.parseString(req.body.toString(), (err, result) => {
if (err) return res.status(400).send('Invalid XML');
console.log(result);
});
});
-
req.body是Buffer,必须先.toString()再喂给xml2js.parseString() - 别用
xml2js.parseStringPromise()直接传Buffer——它不接受二进制,会静默失败 - 大文件(>1MB)慎用
toString(),可能触发内存告警;此时该用xml2js.Parser({ async: true })配合流式解析
为什么XML里中文变成乱码或解析出空对象
XML声明里的编码(如<?xml version="1.0" encoding="GBK"?>)和实际传输编码不一致,是乱码主因。Node.js HTTP模块默认按UTF-8解码,遇到GBK/GB2312就崩。
- 强制统一用UTF-8:让客户端发XML时声明
encoding="UTF-8",且HTTP头Content-Type也带; charset=utf-8 - 实在没法改客户端?用
iconv-lite转码:iconv.decode(req.body, 'gbk')再传给xml2js - 解析后取值为空?检查XML是否含命名空间(
xmlns)。xml2js默认把命名空间当普通属性,需加选项{ mergeAttrs: true, explicitRoot: false }才容易取到result.root.item这类结构
大XML文件上传时内存爆满或超时
Express默认限制req.body最大100KB,express.raw()默认不限但Node.js HTTP服务器有limits,上传几MB的XML很容易卡死或OOM。
- 调大限制:
express.raw({ type: 'application/xml', limit: '5mb' }) - 超时控制:在
app.use()前加app.use((req, res, next) => { req.setTimeout(30000); next(); }) - 真正要处理GB级XML?放弃
req.body,改用req.pipe()直连xml2js.Parser流式解析,避免全量加载到内存
流式解析不是银弹——你要自己处理XML事件(on('opentag')、on('text')),没法一键得JSON。但对日志归档、ETL这类场景,省下的内存和稳定性远比开发多花半小时值。










