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 文件上传

猿创征文|技术成长之路-Java编程系列之文件OSS存储实践:Amazon S3实现文件上传下载

Android Amazon S3文件上传不起作用

从静态网页上传 csv 文件到 S3 存储桶

asp.net core系列 69 Amazon S3 资源文件上传示例