如何使用akka-http在Post Request中一起发送文件和json有效负载

时间:2017-11-20 17:18:22

标签: scala curl akka akka-http

我必须在我的akka​​代码中发送以下curl POST请求,它在请求中发送json有效负载和文件:

curl \
  -F "payload=</tmp/upload_file_payload.json" \
  -F "file=@/tmp/file.pdf" \
   -v https://host/api

我正在尝试在akka-http中实现相同的功能,但不确定如何做到这一点。我找到了一些示例herehere,但它不能正常工作,所以我编写了以下代码,这也有一些错误,但似乎我很接近:

val httpEntity = HttpEntity(MediaTypes.`application/octet-stream`, file, 100000)
//    val httpEntity = HttpEntity.fromPath(ContentType.apply(MediaTypes.`application/octet-stream`), Paths.get(file.getAbsolutePath))
val fileFormData = Multipart.FormData.BodyPart.Strict("file", httpEntity, Map.empty)
val jsonFormData = Multipart.FormData.BodyPart.Strict("payload", payload, Map.empty)


//      Multipart.FormData.Strict(scala.collection.immutable.Seq(jsonFormData, fileFormData)).toEntity()
val entity = Multipart.FormData( Source(List(jsonFormData, fileFormData))).toEntity()
val httpRequest = HttpRequest(HttpMethods.POST, uri = uri, entity = entity)

但是这段代码没有编译。

在两者之间,当我编译代码时,我收到了错误:

  

411长度重新加注

我尝试添加Content-Length标题但请求但无效。

1 个答案:

答案 0 :(得分:2)

最后看了akka-http代码和更多的尝试后,最后我得到了如下工作,在评论中解释:

val httpEntity = HttpEntity(MediaTypes.`application/octet-stream`, file, 100000).toStrict(10.seconds)(mat)   // I had to convert this into strict: which adds Content-Length and tells it is not streaming
val fileFormData = Multipart.FormData.BodyPart.Strict("file", Await.result(httpEntity, 10.seconds), Map.empty)  // used Await here to get httpEntity from Future, this might be made better
val jsonFormData = Multipart.FormData.BodyPart.Strict("payload", payload, Map.empty)

val entity = Multipart.FormData(jsonFormData, fileFormData).toEntity() // Corrected this signature
val httpRequest = HttpRequest(HttpMethods.POST, uri = uri, entity = entity)

为了避免411错误,我必须严格FormData,而且本身会添加必需的Content-Length标题。