Akka HTTP:ByteString 作为表单数据请求中的文件负载
Akka HTTP: ByteString as a file payload in a form-data request
在我的一个 中,我询问了如何使用 Akka HTTP 表示表单数据请求?根据答案,我创建了一个工作示例,但遇到了一个 "scaleability" 问题 - 当表单数据请求数量很高时,我需要处理文件系统中的大量文件。
我很好奇,是否可以在表单数据请求中将 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 给我回了一条消息:
Your video upload timed out before it could be completed. This is
probably because of a slow network connection or because the video
you're trying to upload is too large
但是,如果我发送与 File
相同的 ByteString
,它就可以正常工作。
这可能是什么原因?我已经尝试在 chunkEntity
中使用 MediaTypes.multipart/form-data
但它的行为方式相同。
为了将 ByteString
作为表单数据文件发送,您需要使用以下 BodyPart
:
def fileEntity(chunk: ByteString) = Multipart.FormData.BodyPart.Strict("video_file_chunk",
HttpEntity(ContentType(MediaTypes.`application/octet-stream`), chunk), Map("fileName" -> "video_chunk"))
特别注意Map("fileName" -> "video_chunk")
为了正确构建表单数据 HTTP 请求,此参数是必需的。
因此,不要使用问题中的 chunkEntity
,而是使用此答案中的 fileEntity
:)
在我的一个
我很好奇,是否可以在表单数据请求中将 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 给我回了一条消息:
Your video upload timed out before it could be completed. This is probably because of a slow network connection or because the video you're trying to upload is too large
但是,如果我发送与 File
相同的 ByteString
,它就可以正常工作。
这可能是什么原因?我已经尝试在 chunkEntity
中使用 MediaTypes.multipart/form-data
但它的行为方式相同。
为了将 ByteString
作为表单数据文件发送,您需要使用以下 BodyPart
:
def fileEntity(chunk: ByteString) = Multipart.FormData.BodyPart.Strict("video_file_chunk",
HttpEntity(ContentType(MediaTypes.`application/octet-stream`), chunk), Map("fileName" -> "video_chunk"))
特别注意Map("fileName" -> "video_chunk")
为了正确构建表单数据 HTTP 请求,此参数是必需的。
因此,不要使用问题中的 chunkEntity
,而是使用此答案中的 fileEntity
:)