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 方法不是
POST或PUT - 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.Fileval xmlBytes = "
".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 - test
)
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提高消息队列的实时性方法(推荐)


