在ScalaWS中提交multipart / form-data

时间:2017-07-23 16:44:49

标签: scala playframework

我试图创建一个包含2个部分的帖子:第一部分是json文本,第二部分是二进制音频内容。

发送帖子的代码实际上是:

val ref = UUID.randomUUID()
val requestJobData = s"""
{
   "reference": "$ref",
   "operating_mode": "accurate",
   "callback_url": "http://localhost:8100/",
   "model": { "name": "por-bra" },
   "channels": {
       "firstChannelLabel": {
           "result_format": "transcript",
           "format":"audio/x-wav",
            "num_speakers":2,
        }
   }
}
  """
val jsonPart = DataPart("json", requestJobData)
val filePart = FilePart("firstChannelLabel", "audio(1).wav", Some("audio/x-wav"), FileIO.fromPath(Paths.get("C:\\Input\\_pending\\audio(1).wav")))
val body = Source(filePart :: jsonPart :: List())

val response  =
  client.url(s"$baseUrl")
    .post(body)
    .map {response => response.body[String]}

当我尝试这段代码时,我遇到了这些错误:

Error:(73, 14) Cannot find an instance of akka.stream.scaladsl.Source[Product with Serializable with play.api.mvc.MultipartFormData.Part[akka.stream.scaladsl.Source[akka.util.ByteString,scala.concurrent.Future[akka.stream.IOResult]]],akka.NotUsed] to WSBody. Define a BodyWritable[akka.stream.scaladsl.Source[Product with Serializable with play.api.mvc.MultipartFormData.Part[akka.stream.scaladsl.Source[akka.util.ByteString,scala.concurrent.Future[akka.stream.IOResult]]],akka.NotUsed]] or extend play.api.libs.ws.ahc.DefaultBodyWritables
        .post(body)

Error:(73, 14) not enough arguments for method post: (implicit evidence$3: play.api.libs.ws.BodyWritable[akka.stream.scaladsl.Source[Product with Serializable with play.api.mvc.MultipartFormData.Part[akka.stream.scaladsl.Source[akka.util.ByteString,scala.concurrent.Future[akka.stream.IOResult]]],akka.NotUsed]])scala.concurrent.Future[play.api.libs.ws.StandaloneWSRequest#Response].
Unspecified value parameter evidence$3.
        .post(body)

我的依赖关系是:

scalaVersion := "2.12.1"

libraryDependencies += "org.scalatestplus.play" %% "scalatestplus-play" % "3.1.0" % Test
libraryDependencies += ws
libraryDependencies += guice

libraryDependencies += "com.typesafe" % "config" % "1.3.1"
libraryDependencies ++= Seq(
  "com.typesafe.akka" %% "akka-actor" % "2.5.3",
  "com.typesafe.akka" %% "akka-testkit" % "2.5.3" % Test
)


libraryDependencies += "com.typesafe.play" %% "play-ahc-ws-standalone" % "1.0.0"
libraryDependencies += "com.typesafe.play" %% "play-ws-standalone-json" % "1.0.0"

libraryDependencies ++= Seq(
  "com.github.pureconfig" %% "pureconfig" % "0.7.2"
)

任何人都可以帮忙吗?提前谢谢!

1 个答案:

答案 0 :(得分:1)

由于我需要更快地完成此任务,因此对于此特定部分,我必须切换到另一个名为apache.http(http://hc.apache.org/httpcomponents-client-ga/)的库

这些是我目前的设置:

build.sbt

libraryDependencies ++= Seq(
   "org.apache.httpcomponents" % "httpclient" % "4.3.1",
   "org.apache.httpcomponents" % "httpmime" % "4.3.1"
)

完整的POST示例:

import org.apache.http.client.methods.{HttpGet, HttpPost}
import org.apache.http.entity.ContentType
import org.apache.http.entity.mime.MultipartEntityBuilder
import org.apache.http.impl.client.HttpClients
import org.apache.http.util.EntityUtils

val ref = UUID.randomUUID()
val requestJobData =
  s"""
{
   "reference": "$ref",
   "operating_mode": "accurate",
   "model": { "name": "por-bra" },
   "channels": {
       "firstChannelLabel": {
           "result_format": "lattice",
           "format":"audio/x-wav",
            "num_speakers":2
        }
   }
}
  """

val entity = MultipartEntityBuilder.create()
entity.addTextBody("json", requestJobData, ContentType.APPLICATION_JSON)

val path = Paths.get(audioPath)
val fileName = path.getFileName().toString()
val fileStream = new FileInputStream(audioPath)
entity.addBinaryBody("firstChannelLabel", fileStream, ContentType.create("audio/x-wav"), fileName)
val client = HttpClients.createDefault()
try {
  val post = new HttpPost(baseUrl)
  post.setEntity(entity.build())
  val response = client.execute(post)
}
catch {
  case e: Throwable =>
    log.error("erro ao agendar job: " + e.toString())
}
finally {
  client.close()
}

它真的很有效。我省略了与演员和其他日志记录通信的代码的某些部分,但我希望这对任何人都有帮助。