Amazon S3 存储桶大文件上传
Posted
技术标签:
【中文标题】Amazon S3 存储桶大文件上传【英文标题】:Amazon S3 Bucket Large File Upload 【发布时间】:2018-04-12 09:11:38 【问题描述】:我正在尝试使用 low-level api 使用 java SDK 将大小约为 5 Mb 的 CSV 文件上传到 Amazon S3。
我收到下面提到的错误:。
com.amazonaws.services.s3.model.AmazonS3Exception:指定的 上传不存在。上传 ID 可能无效,或者上传 可能已中止或完成。 (服务:Amazon S3;状态代码: 404;错误代码:NoSuchUpload;请求 ID:)
能否请您提出问题所在。我正在使用us-west-1
区域。
List<PartETag> partETags = new ArrayList<PartETag>();
InitiateMultipartUploadRequest initRequest = new
InitiateMultipartUploadRequest(tempVariableBucketName, tempVariableAccessKey);
InitiateMultipartUploadResult initResponse = s3Client.initiateMultipartUpload(initRequest);
long contentLength = is.available();
long partSize = 1 * 1024 * 1024; // Set part size to 1 MB.
try
long filePosition = 0;
for (int i = 1; filePosition < contentLength; i++)
partSize = Math.min(partSize, (contentLength - filePosition));
logger.info("Upload Id " + initResponse.getUploadId());
UploadPartRequest uploadRequest = new UploadPartRequest()
.withBucketName(tempVariableBucketName).withKey(fileName)
.withUploadId(initResponse.getUploadId()).withPartNumber(i)
.withFileOffset(filePosition)
.withInputStream(is)
.withPartSize(partSize);
partETags.add(s3Client.uploadPart(uploadRequest).getPartETag());
filePosition += partSize;
CompleteMultipartUploadRequest compRequest = new CompleteMultipartUploadRequest(tempVariableBucketName,tempVariableAccessKey,initResponse.getUploadId(),partETags);
s3Client.completeMultipartUpload(compRequest);
catch (Exception e)
logger.error(e.getMessage());
s3Client.abortMultipartUpload(new AbortMultipartUploadRequest(tempVariableBucketName, tempVariableAccessKey, initResponse.getUploadId()));
throw e;
【问题讨论】:
能否提供代码? 我已经发布了代码。 【参考方案1】: Pleas make sure our AWS S3 configuration :
<CORSConfiguration>
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>Authorization</AllowedHeader>
</CORSRule>
</CORSConfiguration>
【讨论】:
感谢 Aman,但此配置已存在于 CORS 配置中的“权限”选项卡下。还是不行。【参考方案2】:您的一个上传失败。您需要从 s3Client.uploadPart() 捕获错误并重试。
我建议对下面的简单代码进行以下改进。
1) 增加每次重试的超时时间。
2) 处理错误类型以确定重试是否有意义。对于某些错误,您应该只报告错误并中止。
3) 将重试次数限制在 10 次左右,以防止永远的 while 循环。
// repeat the upload until it succeeds.
boolean anotherPass;
do
anotherPass = false; // assume everythings ok
try
// Upload part and add response to our list.
partETags.add(s3Client.uploadPart(uploadRequest).getPartETag());
catch (Exception e)
anotherPass = true; // repeat
while (anotherPass);
此 Stack Overflow 问题包含用于改进示例错误处理的代码。
Problems when uploading large files to Amazon S3
【讨论】:
我之前已经浏览过您提到的链接。但是没能成功。每次我收到相同的错误 指定的上传不存在。上传 ID 可能无效,或者上传可能已中止或完成。 我是否需要对上传 ID 进行一些更改? 我已经发布了代码。请你检查一下。我已经添加了重试被阻止并尝试了一次但没有运气。每次重试时,我都会收到相同的错误消息Upload Id is invalid 请使用集成的重试代码更新您的问题。还要添加关于错误的打印声明,以便我们知道您在每个上传部分遇到的错误。【参考方案3】:我能够通过使用 AWS 的 GeneratePresignedUrlRequest 功能解决此问题。 但现在我收到一个新错误。413 request entity too large nginx。我搜索了解决方案,发现我需要在服务器的 nginx.conf 文件中进行更改。 现在问题来了,既然我将拥有多个服务器/负载均衡器实例,那么,我是否必须为每个实例手动设置它?
【讨论】:
您能否详细说明您是如何使用 GeneratePresignedUrlRequest 功能解决此问题的?我遇到了同样的问题,似乎无法使用该功能。以上是关于Amazon S3 存储桶大文件上传的主要内容,如果未能解决你的问题,请参考以下文章
Amazon S3 无法通过 Cloudfront 上传文件
Google App Engine 和 Amazon S3 文件上传