【问题标题】:Sending multi part form data in post method in play/scala在 play/scala 中以 post 方法发送多部分表单数据
【发布时间】:2017-09-15 21:28:04
【问题描述】:

如何在 play scala 中以 post 方法发送多部分表单数据 使用:scalaVersion:2.11.7 playVersion-2.1.5

【问题讨论】:

  • 是的,我已经看过这个文档,这是用于文件上传的我想在 post 中发送一些其他字段作为表单数据,我可以以 json 形式发送数据,但我不能以 form-data 形式发送知道如何邮寄

标签: scala playframework


【解决方案1】:

你需要做一点代码,然后你就可以像使用它了

val data = MultipartFormData(formFields, "asdasboundarystringas")
WS.url(myUrl).post(data.body)

MultipartFormData的代码可以在github上找到: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)
  }

}

符号链接不验证文件部分,所以我不确定,但文件肯定是发送的

更新

具有身份验证和文件验证

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"
}

【讨论】:

  • 谢谢你的回答 :-) 但是你能给我一个模板代码和一个控制器类代码
  • 我可以告诉你我的确切要求是我有四个字段:我从表单中获取的文件,其他三个字段是静态的 我想将所有这四个字段作为表单数据发送到 post url ws.url(myurl).post(data) 但是这里的数据我可以如何在 post 中发送多部分表单数据我需要在这个数据中给出什么你能告诉我
  • 这两个链接我用来解决我的问题但是这段代码对我不起作用,它给出了错误类型不匹配;找到:com.ning.http.client.FluentCaseInsensitiveStringsMap 需要:com.ning.http.client.FluentStringsMap
  • 好吧,看起来他们在一年前为该剧添加了对多部分的支持:groups.google.com/forum/#!msg/play-framework/MPtQlX-cWMQ/…mb 它会帮助你
  • 查看更新部分 - 我对自己的项目进行了验证。你能在 2.1.5 上试试吗?或者 mb 你想在 2.4 上迁移 :)
【解决方案2】:

感谢安德烈库巴!

我做了一些更改(WS.client.underlying 对我不起作用) 我正在运行 play 2.4。

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)
  }
}

这就是我在 Silhouette CookieAuthenticator 中使用它的方式

cookie”是来自登录响应的名为“Set-Cookie”的标头。

WsExtend.postFile(
      url=url,
      files = List("fileparamname" -> filepath),
      bodyParams = List("albumName" -> albumName),
      headers = Map("Cookie" -> cookie)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-04-11
    • 2022-12-05
    • 2017-08-26
    • 1970-01-01
    • 2015-02-14
    • 1970-01-01
    • 2016-06-01
    • 1970-01-01
    相关资源
    最近更新 更多