【发布时间】:2019-02-07 12:14:18
【问题描述】:
我正在尝试使用基于the documentation 的亚马逊 s3 客户端在 Kotlin 中进行简单的概念验证多部分上传。第一部分上传成功,我收到带有 etag 的响应。第二部分没有上传任何东西并且超时。在第一部分之后它总是失败。是否有一些我需要以某种方式手动进行的连接清理?
凭据和权限都很好。下面的神奇数字只是为了达到 5MB 的最小部分大小。
我在这里做错了什么?
fun main() {
val amazonS3 =
AmazonS3ClientBuilder.standard().withRegion(Regions.EU_WEST_1).withCredentials(ProfileCredentialsProvider())
.build()
val bucket = "io.inbot.sandbox"
val key = "test.txt"
val multipartUpload =
amazonS3.initiateMultipartUpload(InitiateMultipartUploadRequest(bucket, key))
var pn=1
var off=0L
val etags = mutableListOf<PartETag>()
for( i in 0.rangeTo(5)) {
val buf = ByteArrayOutputStream()
val writer = buf.writer().buffered()
for(l in 0.rangeTo(100000)) {
writer.write("part $i - Hello world for the $l'th time this part.\n")
}
writer.flush()
writer.close()
val bytes = buf.toByteArray()
val md = MessageDigest.getInstance("MD5")
md.update(bytes)
val md5 = Base64.encodeBytes(md.digest())
println("going to write ${bytes.size}")
bytes.inputStream()
var partRequest = UploadPartRequest().withBucketName(bucket).withKey(key)
.withUploadId(multipartUpload.uploadId)
.withFileOffset(off)
.withPartSize(bytes.size.toLong())
.withPartNumber(pn++)
.withMD5Digest(md5)
.withInputStream(bytes.inputStream())
.withGeneralProgressListener<UploadPartRequest> { it ->
println(it.bytesTransferred)
}
if(i == 5) {
partRequest = partRequest.withLastPart(true)
}
off+=bytes.size
val partResponse = amazonS3.uploadPart(partRequest)
etags.add(partResponse.partETag)
println("part ${partResponse.partNumber} ${partResponse.eTag} ${bytes.size}")
}
val completeMultipartUpload =
amazonS3.completeMultipartUpload(CompleteMultipartUploadRequest(bucket, key, multipartUpload.uploadId, etags))
}
这总是在第二部分失败
Exception in thread "main" com.amazonaws.services.s3.model.AmazonS3Exception: Your socket connection to the server was not read from or written to within the timeout period. Idle connections will be closed. (Service: Amazon S3; Status Code: 400; Error Code: RequestTimeout; Request ID: F419872A24BB5526; S3 Extended Request ID: 48XWljQNuOH6LJG9Z85NJOGVy4iv/ru44Ai8hxEP+P+nqHECXZwWNwBoMyjiQfxKpr6icGFjxYc=), S3 Extended Request ID: 48XWljQNuOH6LJG9Z85NJOGVy4iv/ru44Ai8hxEP+P+nqHECXZwWNwBoMyjiQfxKpr6icGFjxYc=
at com.amazonaws.http.AmazonHttpClient$RequestExecutor.handleErrorResponse(AmazonHttpClient.java:1630)
只是为了抢占一些我不想要的答案,我这样做的目的不是上传文件,而是最终能够通过简单地上传部分直到完成然后组合它们来将任意长度的流传输到 s3。所以,我不能真正使用 TransferManager,因为这需要我提前知道大小,而我不会。此外,我不想将其缓冲为文件,因为这将在 dockerized 服务器应用程序中运行。所以我真的很想上传任意数量的部分。我很高兴按顺序进行;虽然我不介意并行性。
我也使用过“com.github.alexmojaki:s3-stream-upload:1.0.1”,但这似乎在内存中保留了很多状态(我已经用完了几次),所以我'想用更简单的东西代替它。
更新。在下面的 cmets 中感谢 ilya。删除 withFileOffset 可以解决问题。
【问题讨论】:
-
我的猜测是
withFileOffset的调用可能会搞砸事情,你能注释掉这个调用吗?我认为withFileOffset只能与withFile一起使用 -
是的,这行得通。谢谢!