S3 上传程序在尝试上传大文件时抛出异常

Posted

技术标签:

【中文标题】S3 上传程序在尝试上传大文件时抛出异常【英文标题】:S3 uploader throwing exception while trying to upload huge files 【发布时间】:2012-10-11 16:24:56 【问题描述】:

我正在尝试使用适用于 MAC 的 Amazon sdk 上传一个巨大的文件 (8GB)(尽管他们没有适用于 MAC 的 sdk,但我已通过删除 UIKit 引用并为 MAC 重新编译来修改了 ios sdk 源代码)。它实际上适用于文件,可能高达 800MB ~ 1GB。但是每当我尝试上传一个 8GB 的​​文件时,我都会遇到异常。异常说“Internet 连接丢失”。很奇怪,我的互联网连接良好(2Mbps 上传速度:-/)。我正在使用分段上传 api 并上传 5MB 的块。当我遇到异常时,我不会放弃,但我会重试同一块至少 5 次然后放弃。在此重试之间,我睡了几秒钟。但最令人惊奇的是,一旦一个块上传遇到异常,它在重试中就不会真正起作用。我不明白。谁能帮帮我???

提前致谢!

下面我也添加代码!

        fileHandle = [NSFileHandle fileHandleForReadingAtPath:filePath];

        S3InitiateMultipartUploadRequest* initReq = [[S3InitiateMultipartUploadRequest alloc] initWithKey:requestDetails.md5 inBucket:requestDetails.bucket];
        initReq.contentType = requestDetails.contentType;

        S3MultipartUpload* upload = [amazonS3Client_ initiateMultipartUpload:initReq].multipartUpload;
        S3CompleteMultipartUploadRequest* compReq = [[S3CompleteMultipartUploadRequest alloc] initWithMultipartUpload:upload];


        compReq.contentType = requestDetails.contentType;

        NSData* data = [fileHandle readDataOfLength:PART_SIZE];
        int part = 0;
        ...............................
        while([data length] > 0)
        
                @try 
                    S3UploadPartRequest* upReq = [[S3UploadPartRequest alloc] initWithMultipartUpload:upload];
                    upReq.partNumber = part + 1;
                    upReq.contentLength = data.length;
                    upReq.data = data;
                    upReq.contentType = requestDetails.contentType;

                    response = [amazonS3Client_ uploadPart:upReq];
                    [compReq addPartWithPartNumber:(part + 1) withETag:response.etag];

                    offset += [data length];

                    [fileHandle seekToFileOffset:offset];
                    data = [fileHandle readDataOfLength:PART_SIZE];
                    part++;
                    ........................
                
                @catch (AmazonClientException *exception) 
                    .............................

                    if([exception.message rangeOfString:@"expire"].location != NSNotFound)
                    
                        // renew credentials code 
                        return [self multipartUpload:requestDetails withFilePath:filePath];
                    

                
            
      [amazonS3Client_ completeMultipartUpload:compReq];

【问题讨论】:

【参考方案1】:

我是适用于 iOS 的 AWS 开发工具包的维护者之一。虽然我们还没有测试过这种大小的文件,但我想不出 SDK 中有任何东西会导致这种情况。您可能想尝试和/或包含在您的问题中的一些事情:

    最新版本的适用于 iOS 的 AWS 开发工具包包含一个选项,用于禁用开发工具包本身的异常。这可能显示异常的来源是在 SDK 中还是在其他地方。

    您说您正在重试异常,但您是重新使用请求还是创建新请求?包含您的代码可能有助于其他人提供建议。

    当你进入这个状态时,你可以执行任何其他操作吗?您确定您的网络连接没有以某种方式重置吗?

跟进

过去几天,我花了很多时间尝试使用最新版本的适用于 iOS 的 AWS 开发工具包重现该问题,但没有成功。我能够使用分段上传成功地将 10GB 文件上传到 Amazon S3。

我想总结一些发现并为下一步提出一些建议:

    您确实应该更新 SDK。自您说下载以来,AWS SDK for iOS 在 6 个月内已经进行了许多更新,其中一些与连接处理有关,这可能有助于解决此问题。

    您的 Internet 连接测试可能没有测试正确的内容。您没有包含此代码,因此不清楚,但如果您正在测试的只是本地设备具有链接并且可以访问其网关,那么这不一定是您的没有问题的有效指标连接到 Amazon S3。您遇到超时(稍后会详细介绍)这一事实表明您的计算机在连接到 Amazon S3 时遇到了问题。发生这种情况的原因有很多,包括网络硬件故障或您的 ISP 明确的流量整形。

    SDK 在超时处理方面存在不一致。对于除 S3 之外的所有客户端,超时应用于 NSURLConnection 对象以及处理实际请求。对于 S3,它仅适用于请求的处理,这意味着 NSURLConnection timeoutInverval 属性未修改。 NSURLConnection timeoutInterval 属性是建立连接的超时时间。一旦数据被发送或接收,即使只是涓涓细流,NSURLConnection 也不会超时。这意味着,如果您收到超时异常,您的计算机无法在默认 timeoutInterval (60s) 内建立到 Amazon S3 的连接。我们将审查并酌情修补 SDK 以解决此不一致问题。

    正如我在原始答案中所述,最好确认您是否可以向 Amazon S3 发出另一个请求(如列表存储桶/对象)以及访问另一个外部资源(如 google.com)你进入这种失败状态。这至少可以让你找到你的 ISP 并就正在发生的事情提出更好的问题。

希望这些信息对您有所帮助

【讨论】:

感谢您的回复!我已经粘贴了上面的代码。你可以通过它。并回答您的问题 1:我可能使用的是旧版本。我在 6 个月前下载了它。 2:在每次重试中都会创建一个新请求。您可以在代码中看到它。 3:当我遇到异常时,我很确定我有连接。还有一点需要注意的是,对于大文件,我也遇到了另一个例外。它说“请求超时”,尽管我已将“INT_MAX”设置为超时值:-o 要明确:是上传部分请求的例外情况还是您检查互联网连接时的例外情况? @Advaith 很抱歉询问更多信息,但如果您可以包含来自 AmazonLogger 的其他日志记录,这也可能有助于诊断问题。我同意你会得到如此大的超时值是很奇怪的。您肯定是以超出我们支持的用例的方式使用 SDK,但我们会看看是否可以提供帮助。 我抛出异常只是为了确保,如果我的异常是由于缺乏互联网连接,我不想重试。我调试了它并没有进入。它是从'if(retryCount> 5)'条件抛出的。这就是为什么我说我很确定我不会失去互联网连接。助教 :) @Advaith 关于超时错误:S3 客户端设置超时值大于默认值有一个错误,所以如果您的请求花费的时间超过 240 秒(我认为 OS X 上的默认值为 60 秒)它无论在 S3 客户端上设置什么超时值,都会超时。我们将在 SDK 中解决这个问题。

以上是关于S3 上传程序在尝试上传大文件时抛出异常的主要内容,如果未能解决你的问题,请参考以下文章

org.eclipse.jetty.io.EofException:上传大文件时抛出早期 EOF

实体框架在使用 Find 方法时抛出异常

Firebase Storage 在图像上传时抛出错误(Nodejs)

try-catch异常处理

Android 5.0+ MediaPlayer 在尝试播放 OPUS 文件时抛出 PreparedFailed 异常

退出程序时抛出异常(Ogre3d)