Scala Play框架如何处理XML文件上传 MultipartFormData

发布时间 - 2026-02-02 00:00:00    点击率:
Play 2.8+ 中需手动提取 FilePart 并用禁用 DTD 的 SAXParser 安全解析 XML,避免 OOM 和 XXE;request.body.asMultipartFormData() 返回 null 多因 enctype、HTTP 方法、路由或 Content-Type 错误。

Play 2.8+ 中如何接收 XML 文件上传(MultipartFormData

Play 默认不自动解析 multipart 请求中的 XML 文件体——它只把整个 part 当作原始字节流或字符串处理,不会像 JSON 那样触发隐式反序列化。你必须手动提取 FilePart,再读取其内容并解析为 XML。

request.body.asMultipartFormData() 返回 null 的常见原因

这个方法返回 null 通常不是因为没传文件,而是请求根本没走对路:

  • 前端没设 enctype="multipart/form-data"(比如用 application/json 发送)
  • HTTP 方法不是 POSTPUT
  • Play 路由没匹配到对应 action(比如用了 GET 路由去接上传)
  • Content-Type 头缺失或格式错误(如写成 multipart/form-data; 少了 boundary)

检查日志里是否有 WARN - Body parser failed: MultipartFormData body parsing failed,这说明解析器中途放弃了。

安全地读取并解析 XML 文件内容(避免 OOM 和 XXE)

直接调用 filePart.ref().path 拿到临时文件路径后,不能用 scala.xml.XML.load() —— 它默认启用 DTD 解析,存在 XXE 漏洞;也不能无限制读大文件进内存。

import javax.xml.parsers.SAXParserFactory
import org.xml.sax.helpers.DefaultHandler
import play.api.mvc._

def uploadXml = Action(parse.multipartFormData) { request => request.body.file("xmlFile") match { case Some(filePart) => val factory = SAXParserFactory.newInstance() factory.setFeature("https://www./link/bdc31e3996f71d8f34782dda5ea48511", true) factory.setFeature("https://www./link/4d1025a728b16caa6ca38ed00c663e68", false) factory.setFeature("https://www./link/a6668ef0ca3092b1efab304fbf65e4e6", false)

  val parser = factory.newSAXParser()
  val handler = new DefaultHandler() // 替换为你自己的逻辑
  parser.parse(filePart.ref().path.toFile, handler)

  Ok("XML parsed safely")
case None =youjiankuohaophpcn BadRequest("Missing file part 'xmlFile'")

} }

关键点:

  • SAXParser 替代 scala.xml.XML,控制内存占用
  • 显式禁用 DTD、外部实体(disallow-doctype-decl 等三项必须设为 true
  • filePart.ref().path 是 Play 自动保存的临时文件,无需自己流式复制
  • 字段名 "xmlFile" 必须和 HTML 表单中 一致

如何在测试中模拟 XML 文件上传

Helpers.route() + MultipartFormData 构造体时,别直接塞字符串——Play 的测试工具链要求你提供 FilePart 的二进制数据和 MIME 类型:

import play.api.test._
import java.io.File

val xmlBytes = "test".getBytes("UTF-8") val formData = MultipartFormData[TemporaryFile]( dataParts = Map.empty, files = Seq( FilePart("xmlFile", "data.xml", Some("application/xml"), TemporaryFile("test.xml", xmlBytes)) ), badParts = Seq.empty

)

val request = FakeRequest(POST, "/upload").withMultipartFormDataBody(formData) val result = route(app, request).get

注意:TemporaryFile 构造器第二个参数是 Array[Byte],不是 String;MIME 类型写 "application/xml""text/xml" 更稳妥,部分浏览器和 Play 内部逻辑会据此做不同处理。

临时文件路径和解析时机容易混淆:Play 在 action 执行前就已把上传文件落地为磁盘临时文件,filePart.ref().path 是真实可读的路径,但该文件会在 action 返回后被自动清理——所以不要在异步逻辑里延迟读取,否则可能报 No such file


# java  # html  # js  # 前端  # json  # apache  # 浏览器  # app  # 字节  # 工具  # ai  # 路由  # win  # 内存占用  # String  # Array  # NULL  # xml  # 字符串  # 异步  # input  # http  # 临时文件  # 自己的  # 文件上传  # 为你  # 设为  # 会在  # 用了  # 第二个  # 少了  # 不能用 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: 如何基于云服务器快速搭建个人网站?  linux写shell需要注意的问题(必看)  东莞市网站制作公司有哪些,东莞找工作用什么网站好?  iOS UIView常见属性方法小结  如何用搬瓦工VPS快速搭建个人网站?  ,南京靠谱的征婚网站?  Laravel如何将应用部署到生产服务器_Laravel生产环境部署流程  Laravel的路由模型绑定怎么用_Laravel Route Model Binding简化控制器逻辑  怎么用AI帮你为初创公司进行市场定位分析?  Laravel如何实现图片防盗链功能_Laravel中间件验证Referer来源请求【方案】  如何在Windows 2008云服务器安全搭建网站?  Laravel用户认证怎么做_Laravel Breeze脚手架快速实现登录注册功能  长沙企业网站制作哪家好,长沙水业集团官方网站?  三星、SK海力士获美批准:可向中国出口芯片制造设备  Laravel怎么在Blade中安全地输出原始HTML内容  武汉网站设计制作公司,武汉有哪些比较大的同城网站或论坛,就是里面都是武汉人的?  Laravel软删除怎么实现_Laravel Eloquent SoftDeletes功能使用教程  JavaScript如何实现继承_有哪些常用方法  专业型网站制作公司有哪些,我设计专业的,谁给推荐几个设计师兼职类的网站?  Laravel Eloquent性能优化技巧_Laravel N+1查询问题解决  Android自定义控件实现温度旋转按钮效果  大连企业网站制作公司,大连2025企业社保缴费网上缴费流程?  如何快速重置建站主机并恢复默认配置?  Laravel Blade组件怎么用_Laravel可复用视图组件的创建与使用  Laravel如何使用Facades(门面)及其工作原理_Laravel门面模式与底层机制  邀请函制作网站有哪些,有没有做年会邀请函的网站啊?在线制作,模板很多的那种?  PythonWeb开发入门教程_Flask快速构建Web应用  Laravel策略(Policy)如何控制权限_Laravel Gates与Policies实现用户授权  Swift中switch语句区间和元组模式匹配  Windows家庭版如何开启组策略(gpedit.msc)?(安装方法)  Laravel如何创建自定义中间件?(Middleware代码示例)  教你用AI润色文章,让你的文字表达更专业  瓜子二手车官方网站在线入口 瓜子二手车网页版官网通道入口  EditPlus 正则表达式 实战(3)  如何在万网自助建站中设置域名及备案?  Laravel如何与Pusher实现实时通信?(WebSocket示例)  php结合redis实现高并发下的抢购、秒杀功能的实例  javascript基于原型链的继承及call和apply函数用法分析  Laravel如何使用模型观察者?(Observer代码示例)  html5的keygen标签为什么废弃_替代方案说明【解答】  Laravel的HTTP客户端怎么用_Laravel HTTP Client发起API请求教程  javascript和jQuery中的AJAX技术详解【包含AJAX各种跨域技术】  Laravel如何使用Service Container和依赖注入?(代码示例)  Laravel如何从数据库删除数据_Laravel destroy和delete方法区别  Laravel怎么判断请求类型_Laravel Request isMethod用法  js实现点击每个li节点,都弹出其文本值及修改  公司门户网站制作流程,华为官网怎么做?  进行网站优化必须要坚持的四大原则  大连网站制作公司哪家好一点,大连买房网站哪个好?  phpredis提高消息队列的实时性方法(推荐)