如何通过请求体传值发送POST请求?含Play框架相关疑问
问题解答
1. 路由中_ids的下划线含义
Play框架路由里的下划线_就是普通的URL路径字符,没有特殊语法作用。它只是用来做语义化标识,说明这个接口是通过ID列表导出数据,你完全可以换成/games/export/ids这类名称,框架只会把整个/games/export/_ids当作匹配的URL路径,不会对下划线做额外解析。
2. Form表单向请求体传值的方法
你的Action用parse.tolerantText解析纯文本请求体,但默认HTML表单提交的是application/x-www-form-urlencoded格式,两者不兼容,有两种解决思路:
方法一:适配表单格式修改Action解析器
把Action的解析器改成parse.formUrlEncoded,从表单参数中提取ID列表:
def exportByIds = Action.async(parse.formUrlEncoded) { req => val ids = req.body.get("ids") .flatMap(_.headOption) .map(_.split(',')) .getOrElse(Array.empty[String]) download(ids) }
对应的表单需要添加隐藏输入框来传递ID列表:
form( noFollow, cls := "button", action := s"${routes.Game.exportByIds}", method := "POST" ) { input( `type` := "hidden", name := "ids", value := "1,2,3" // 替换为实际的ID列表字符串 ) button(`type` := "submit", "导出") }
方法二:通过JS让表单提交纯文本
如果坚持用parse.tolerantText,需要用JavaScript拦截表单提交,手动构造纯文本请求体:
form( noFollow, cls := "button", action := s"${routes.Game.exportByIds}", method := "POST", onsubmit := "handleSubmit(event)" ) { input( `type` := "hidden", id := "idsInput", value := "1,2,3" ) button(`type` := "submit", "导出") }
配套的JS代码:
function handleSubmit(event) { event.preventDefault(); const form = event.target; const ids = document.getElementById('idsInput').value; fetch(form.action, { method: 'POST', body: ids, headers: { 'Content-Type': 'text/plain' } }).then(response => { if (response.ok) { response.blob().then(blob => { const url = URL.createObjectURL(blob); const a = document.createElement('a'); a.href = url; a.download = 'export.csv'; // 替换为你的导出文件名 a.click(); URL.revokeObjectURL(url); }); } }); }
3. WS发送POST请求的类型不匹配问题
大概率是请求体类型和parse.tolerantText解析器不兼容,正确的WS发送纯文本请求写法如下:
import play.api.libs.ws._ ws.url(routes.Game.exportByIds.url) .withHttpHeaders("Content-Type" -> "text/plain") .post("1,2,3") // 直接传递ID列表字符串,与Action解析器对应 .map { response => // 处理响应逻辑 }
如果之前传的是JSON或表单格式参数,就会和纯文本解析器冲突,导致类型错误,确保请求体是纯文本字符串且设置正确的Content-Type头。
内容的提问来源于stack exchange,提问作者Erdogan Seref
相关产品推荐
相关产品推荐

