我正在尝试使用akka-http通过基本的S3兼容API实现文件存储功能。
我使用s3 java sdk来测试我的服务API,并遇到了putObject(...)方法的问题。我在akka-http后端上无法正确使用文件。我为测试目的写了简单的路线:
def putFile(bucket: String, file: String) = put{
extractRequestEntity{ ent =>
val finishedWriting = ent.dataBytes.runWith(FileIO.toPath(new File(s"/tmp/${file}").toPath))
onComplete(finishedWriting) { ioResult =>
complete("Finished writing data: " + ioResult)
}
}
}
它保存文件,但是文件总是损坏的。查看文件内部,发现以下行:
"20000;chunk-signature=73c6b865ab5899b5b7596b8c11113a8df439489da42ddb5b8d0c861a0472f8a1"
。
当我尝试与其他任何其他客户端PUT文件时,它的工作效果都与预期的一样。 我知道S3使用“期望:100-继续”标题,可能会引起问题。 我真的不知道该如何处理。任何帮助表示赞赏。
答案 0 :(得分:0)
这并没有完全损坏。您的服务无法解决S3支持使用Content-Encoding: aws-chunked
和x-amz-content-sha256: STREAMING-AWS4-HMAC-SHA256-PAYLOAD
通过网络发送的四种方式之一。
这是一种用于流对象的基于非标准的机制,其中包括看起来完全像这样的块:
string(IntHexBase(chunk-size)) + ";chunk-signature=" + signature + \r\n + chunk-data + \r\n
...其中IntHexBase()
是用于将整数格式化为十六进制数字作为字符串的函数的伪代码。
此chunk-based algorithm与Transfer-Encoding: chunked
类似,但不兼容,因为它在流中嵌入了校验和。
为什么它们要组成新的HTTP传输编码?它在客户端可能很有用,因为它消除了对"read your payload twice or buffer [the entire object payload] in memory [concurrently]"的需求-如果要在上载开始之前计算x-amz-content-sha256
哈希,则不需要其中一个或另一个否则必须这样做,因为完整性检查是必需的。
我不太熟悉Java SDK的内部原理,但是这种上载类型可能可以通过使用.withInputStream()
来触发,或者它也可能是文件的标准行为,或者对于文件超过一定大小。
如果您在请求标头中看到x-amz-content-sha256: STREAMING-AWS4-HMAC-SHA256-PAYLOAD
,则您的最小解决方法是抛出HTTP错误,因为您似乎未在API中实现此错误,但这很可能仅用于防止存储由这种方法。这还不是自动发生的事实,这表明您根本没有实现x-amz-content-sha256
处理,因此您没有在进行服务器端有效载荷完整性检查。
为获得完全兼容性,您将需要实现S3支持的算法并假定SDK可以使用该算法,除非SDK特别支持一种禁用该算法的机制-这似乎不太可能,因为它具有有用的用途,(尤其是(对于它)对于长度已知但不可搜索的流。
¹四个之一-其他三个是标准PUT
,基于Web的html格式POST
和建议用于大型文件的多部分API对于大于5 GB的文件是必需的。