ASP.NET Core 中用 IFormFile 接收 XML 文件需直接读取流并用 XDocument.Load 或 XmlReader 安全解析,禁用 DTD 和外部实体以防 XXE,校验 ContentType 并处理 BOM 与编码声明。
ASP.NET Core 中用 IFormFile 接收 XML 文件上传
XML 文件本质是文本,只要前端按普通文件上传,后端就能拿到原始字节流。关键不是“XML 特殊”,而是别把它当二进制乱解析——尤其别用 StreamReader 默认编码读取,容易因 BOM 或声明里的 encoding 属性出错。
实操建议:
- 控制器方法参数直接接收
IFormFile,不要依赖模型绑定自动转成字符串或对象 - 用
file.OpenReadStream()获取流,再交给XDocument.Load()或XmlSerializer解析,它们会自动识别编码声明(如) - 若需先保存再处理,用
file.CopyToAsync()写入临时文件,路径别硬写C:\temp,改用Path.GetTempFileName() - 务必校验
file.ContentType是否为text/xml或application/xml,但不能仅靠它拦截——MIME 类型可被伪造
ASP.NET Framework(.NET 4.x)中用 Request.Files 读取 XML
老版本没有 IFormFile,得从 Request.Files[0] 拿 HttpPostedFileBase。它暴露的是原始流,但注意:如果启用了 requestValidationMode="4.5",含尖括号的 XML 可能触发 HttpRequestValidationException。
实操建议:
- 在对应 Action 上加
[ValidateInput(false)],否则带的 XML 直接 500 - 用
file.InputStream构造XmlReader.Create(),别用file.FileName去磁盘找文件——它只是客户端传来的名字,不保证存在 - 若 XML 很大(>1MB),避免一次性
ReadToEnd()转字符串,改用流式解析(XmlReader.Read()循环)防内存溢出 -
file.ContentLength是字节数,不是字符数;检查是否为 0 再读流,否则XmlDocument.Load()会抛XmlException
解析时遇到 “Data at the root level is invalid” 错误
这是 XmlDocument.Load() 或 XDocument.Load() 最常见的报错,90% 是因为流位置不在开头,或内容被提前读过一次。