首页 > 解决方案 > Akka HTTP:ByteString 作为表单数据请求中的文件有效负载

问题描述

在我之前的一个问题中,我问过如何使用 Akka HTTP 表示表单数据请求?根据答案,我创建了一个工作示例,但面临“可扩展性”问题 - 当表单数据请求的数量很高时,我需要处理文件系统中的大量文件。

我很好奇,是否可以ByteString在表单数据请求中作为文件有效负载发送?

case class FBSingleChunkUpload(accessToken: String, 
        sessionId: String,
        from: Long, 
        to: Long, 
        file: ByteString) //this property is received from S3 as array of bytes

我创建了以下示例:

def defaultEntity(content: String) =
  HttpEntity.Default(
    ContentTypes.`text/plain(UTF-8)`,
    content.length, Source(ByteString(content) :: Nil)
  )

def chunkEntity(chunk: ByteString) =
  HttpEntity.Strict(
    ContentType(MediaTypes.`application/octet-stream`),
    chunk
  )

val formData = Multipart.FormData(
  Source(
    Multipart.FormData.BodyPart("access_token", defaultEntity(upload.fbUploadSession.fbId.accessToken)) ::
    Multipart.FormData.BodyPart("upload_phase", defaultEntity("transfer")) ::
    Multipart.FormData.BodyPart("start_offset", defaultEntity(upload.fbUploadSession.from.toString)) ::
    Multipart.FormData.BodyPart("upload_session_id", defaultEntity(upload.fbUploadSession.uploadSessionId)) ::
    Multipart.FormData.BodyPart("video_file_chunk", chunkEntity(upload.chunk)) :: Nil
  )
)
val req = HttpRequest(
  HttpMethods.POST,
  s"/v2.3/${upload.fbUploadSession.fbId.pageId}/videos",
  Nil,
  formData.toEntity()
)

在这种情况下,Facebook 会给我发回一条消息:

您的视频上传在完成之前超时。这可能是因为网络连接速度较慢或您尝试上传的视频太大

但是,如果我发送与 a 相同ByteString的内容,File则效果很好。

这可能是什么原因?我已经尝试使用MediaTypes.multipart/form-datainchunkEntity但它的行为方式相同。

标签: scalafacebook-graph-apiakkaakka-http

解决方案


为了将 aByteString作为表单数据文件发送,您需要使用以下内容BodyPart

def fileEntity(chunk: ByteString) = Multipart.FormData.BodyPart.Strict("video_file_chunk",
    HttpEntity(ContentType(MediaTypes.`application/octet-stream`), chunk), Map("fileName" -> "video_chunk"))

要正确构造表单数据 HTTP 请求,必须特别注意Map("fileName" -> "video_chunk")此参数。

因此,不要chunkEntity从问题中使用,而是fileEntity从这个答案中使用:)


推荐阅读