如何在play scala中的post方法中发送多部分表单数据 使用:scalaVersion:2.11.7 playVersion-2.1.5
答案 0 :(得分:8)
你需要做一些代码,然后就可以像
那样使用它val data = MultipartFormData(formFields, "asdasboundarystringas")
WS.url(myUrl).post(data.body)
您可以在github上找到MultipartFormData的代码:https://gist.github.com/EECOLOR/7649144
<强>更新强>
另一种方法,我一直尝试使用Play 2.4.3
package controllers
import play.api.Play.current
import play.api.libs.ws._
import play.api._
import play.api.mvc._
import com.ning.http.client.AsyncHttpClient
import com.ning.http.client.multipart.FilePart
import com.ning.http.client.multipart.StringPart
import java.io.File
class Application extends Controller {
def index = Action {
val url = "http://symlink.dk/code/php/submit/"
val asyncHttpClient:AsyncHttpClient = WS.client.underlying
val postBuilder = asyncHttpClient.preparePost("http://symlink.dk/code/php/submit/")
val builder = postBuilder.addBodyPart(new StringPart("myField", "abc", "UTF-8"))
.addBodyPart(new StringPart("myField1", "abc1", "UTF-8"))
.addBodyPart(new StringPart("myField2", "abc2", "UTF-8"))
.addBodyPart(new FilePart("myFile", new File("app/controllers/Application.scala")))
val response = asyncHttpClient.executeRequest(builder.build()).get();
Ok(response.getResponseBody)
}
}
Symlink不验证文件部分,所以我不确定它,但文件肯定是发送
<强>更新强>
使用身份验证和文件验证
package controllers
import play.api.Play.current
import play.api.libs.ws._
import play.api._
import play.api.mvc._
import com.ning.http.client.AsyncHttpClient
import com.ning.http.client.multipart.FilePart
import com.ning.http.client.multipart.StringPart
import java.io.File
import org.apache.commons.codec.binary.Base64.encodeBase64
class Application extends Controller {
def index = Action {
val url = "http://httpbin.org/post"
val name = "MyUserName"
val password = "MyPassword"
val encodedCredentials =
new String(encodeBase64("%s:%s".format(name, password).getBytes))
val asyncHttpClient:AsyncHttpClient = WS.client.underlying
val postBuilder = asyncHttpClient.preparePost(url)
val builder = postBuilder
.addHeader("Authorization", "Basic " + encodedCredentials)
.addBodyPart(new StringPart("myField", "abc", "UTF-8"))
.addBodyPart(new StringPart("myField1", "abc1", "UTF-8"))
.addBodyPart(new StringPart("myField2", "abc2", "UTF-8"))
.addBodyPart(new FilePart("myFile", new File("app/controllers/Application.scala")))
val response = asyncHttpClient.executeRequest(builder.build()).get();
Ok(response.getResponseBody)
}
}
发布数据的回声:
{
"args": {},
"data": "",
"files": {
"myFile": "package controllers\n\nimport play.api.Play.current\nimport play.api.libs.ws._\nimport play.api._\nimport play.api.mvc._\nimport com.ning.http.client.AsyncHttpClient\nimport com.ning.http.client.multipart.FilePart\nimport com.ning.http.client.multipart.StringPart\nimport java.io.File\nimport org.apache.commons.codec.binary.Base64.encodeBase64\n\nclass Application extends Controller {\n\n def index = Action {\n// val url = \"http://symlink.dk/code/php/submit/\"\n val url = \"http://httpbin.org/post\"\n\n val name = \"MyUserName\"\n val password = \"MyPassword\"\n\n val encodedCredentials =\n new String(encodeBase64(\"%s:%s\".format(name, password).getBytes))\n\n val asyncHttpClient:AsyncHttpClient = WS.client.underlying\n val postBuilder = asyncHttpClient.preparePost(url)\n val builder = postBuilder\n .addHeader(\"Authorization\", \"Basic \" + encodedCredentials)\n .addBodyPart(new StringPart(\"myField\", \"abc\", \"UTF-8\"))\n .addBodyPart(new StringPart(\"myField1\", \"abc1\", \"UTF-8\"))\n .addBodyPart(new StringPart(\"myField2\", \"abc2\", \"UTF-8\"))\n .addBodyPart(new FilePart(\"myFile\", new File(\"app/controllers/Application.scala\")))\n val response = asyncHttpClient.executeRequest(builder.build()).get();\n Ok(response.getResponseBody)\n }\n\n}\n"
},
"form": {
"myField": "abc",
"myField1": "abc1",
"myField2": "abc2"
},
"headers": {
"Accept": "*/*",
"Authorization": "Basic TXlVc2VyTmFtZTpNeVBhc3N3b3Jk",
"Content-Length": "1991",
"Content-Type": "multipart/form-data; boundary=ZUeOacX0k9AyI7O12kXDuV5gucDyh2IcA",
"Host": "httpbin.org",
"User-Agent": "AHC/1.0"
},
"json": null,
"origin": "111.111.111.11",
"url": "http://httpbin.org/post"
}
<强>更新强>
只是为了澄清 - 如果您不需要将文件作为表单的一部分发送,那么您不需要访问底层WSClient并且可以使用普通的WS
val url = "http://httpbin.org/post"
val name = "MyUserName"
val password = "MyPassword"
val result = WS.url(url)
.withAuth(name, password, WSAuthScheme.BASIC)
.post(
Map(
"myField" -> Seq("myValue"),
"myField1" -> Seq("myValue1"),
"myField2" -> Seq("myValue2")
)
)
val response = Await.result(result, 10 seconds)
Ok(response.body)
请求此代码发送:
{
"args": {},
"data": "",
"files": {},
"form": {
"myField": "myValue",
"myField1": "myValue1",
"myField2": "myValue2"
},
"headers": {
"Accept": "*/*",
"Authorization": "Basic TXlVc2VyTmFtZTpNeVBhc3N3b3Jk",
"Content-Length": "51",
"Content-Type": "application/x-www-form-urlencoded; charset=utf-8",
"Host": "httpbin.org",
"User-Agent": "AHC/1.0"
},
"json": null,
"origin": "111.111.111.11",
"url": "http://httpbin.org/post"
}
答案 1 :(得分:1)
谢谢Andriy Kuba!
我做了一些改动(WS.client.underlying对我不起作用) 我正在玩2.4。
HashDiff
这就是我使用Silhouette CookieAuthenticator
的方式&#34;的饼干强>&#34;是一个标题为&#34; Set-Cookie &#34;来自登录回复。
package utils
import com.ning.http.client.{AsyncHttpClient, ListenableFuture, Request, Response}
import com.ning.http.client.cookie.Cookie
import com.ning.http.client.multipart.{FilePart, StringPart}
/**
* Created by ozma on 27/05/16.
*/
object WsExtend {
def postFile(url: String,
files: List[(String, String)] = List(),
bodyParams: List[(String, String)] = List(),
cookies: List[Cookie] = List(),
headers: Map[String, String] = Map(),
encoding: String = "UTF-8"): Response = {
postFileAsync(url, files, bodyParams, cookies, headers, encoding).get()
}
def postFileAsync(url: String,
files: List[(String, String)] = List(),
bodyParams: List[(String, String)] = List(),
cookies: List[Cookie] = List(),
headers: Map[String, String] = Map(),
encoding: String = "UTF-8"): ListenableFuture[Response] = {
val asyncHttpClient:AsyncHttpClient = new AsyncHttpClient()
val postBuilder: AsyncHttpClient#BoundRequestBuilder = asyncHttpClient.preparePost(url)
files.foreach(e => postBuilder.addBodyPart(new FilePart(e._1, new java.io.File(e._2))))
bodyParams.foreach(e => postBuilder.addBodyPart(new StringPart(e._1, e._2, encoding)))
cookies.foreach(c => postBuilder.addCookie(c))
headers.foreach(h => postBuilder.addHeader(h._1, h._2))
val request: Request = postBuilder.build()
asyncHttpClient.executeRequest(request)
}
}
答案 2 :(得分:0)
这是使用 Play 2.6.x 对Instagram API进行身份验证的示例:
def getAccessToken(code: String): Future[String] = {
val start = System.currentTimeMillis()
val data = Map(
"client_id" -> Seq(clientId),
"client_secret" -> Seq(clientSecret),
"redirect_uri" -> Seq(redirectUri),
"grant_type" -> Seq("authorization_code"),
"code" -> Seq(code))
ws.url("https://api.instagram.com/oauth/access_token")
.post(data)
.map {
response =>
(response.json \ "access_token").as[String]
}
.recover {
case ex: Exception =>
logger.error("Could not get access token", ex)
throw ex
}
}