使用Swift使用AWS sdk v2上传S3视频失败



我正在尝试使用最新的(v2.2.2) AWS SDK将视频文件上传到S3。它在WiFi上运行得很好,但由于某种不知道的原因,每次在同一地点使用3G时都会出现故障。查看详细的调试输出,似乎每次都得到5个块,这似乎奇怪地一致。

我的上传代码是:

let credentialsProvider = CustomAmazonCredentialsProvider(accessKey: json["credentials"]["key"].stringValue, secretKey: json["credentials"]["secret"].stringValue, sessionKey: json["credentials"]["token"].stringValue)
            let configuration : AWSServiceConfiguration = AWSServiceConfiguration(region: AWSRegionType.EUWest1, credentialsProvider: credentialsProvider)
            configuration.maxRetryCount = 10;

            AWSServiceManager.defaultServiceManager().defaultServiceConfiguration = configuration
            let filePath : String! = json["file_path"].stringValue
            AWSS3.registerS3WithConfiguration(configuration, forKey: filePath)
            AWSS3TransferManager.registerS3TransferManagerWithConfiguration(configuration, forKey: filePath)
            let uploadRequest : AWSS3TransferManagerUploadRequest = AWSS3TransferManagerUploadRequest()
            let file : String = json["file_path"].stringValue
            uploadRequest.body = NSURL(fileURLWithPath: self.videoPath!) //self.moviePlayer!.contentURL
            uploadRequest.key = file
            uploadRequest.bucket = json["bucket"].stringValue
            self.uploadRequests.append(uploadRequest)
            self.transferManager  = AWSS3TransferManager.S3TransferManagerForKey(json["file_path"].stringValue)

            uploadRequest.uploadProgress = {[unowned self](bytesSent:Int64,
                totalBytesSent:Int64, totalBytesExpectedToSend:Int64) in
                dispatch_sync(dispatch_get_main_queue(), { () -> Void in
                    var progress : CGFloat = CGFloat(totalBytesSent) / CGFloat(totalBytesExpectedToSend)
                    println("prog (progress)")
                    println("total (totalBytesSent)")
                    println("total (totalBytesExpectedToSend)")
                    if ( progress < 1.0 ) {
                        SVProgressHUD.showProgress(Float((CGFloat(totalBytesSent) / CGFloat(totalBytesExpectedToSend))), status: "Uploading", maskType: SVProgressHUDMaskType.None)

                    }
                })
            }

            self.transferManager!.upload(uploadRequest).continueWithBlock({ (task) -> AnyObject! in
            ...
          })

我很确定我有参考的一切,就像我说的,它在WiFi上工作得很好,所以为什么它会在移动网络上连续5块失败?

更新:

下面是一些调试输出:

2015-07-29 10:34:55.938 Constent[6229:586874] AWSiOSSDKv2 [Debug] AWSSignature.m line:653 | -[AWSS3ChunkedEncodingInputStream nextChunk] | stream read: 32677, chunk size: 32768
2015-07-29 10:34:55.947 Constent[6229:586874] AWSiOSSDKv2 [Debug] AWSSignature.m line:669 | -[AWSS3ChunkedEncodingInputStream getSignedChunk:] | AWS4 String to Sign: [AWS4-HMAC-SHA256-PAYLOAD
20150729T093445Z
20150729/eu-west-1/s3/aws4_request
b1553d25ed783a533cd12380d9df4354f6d331d646692d4401b802cc30348502
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
70d7035aabde0212f688146957761f57dc68cab99dddb31ec0878aea6d222292]
prog 0.0495226365596895
total 98031
total 1979519
2015-07-29 10:34:55.951 Constent[6229:586874] AWSiOSSDKv2 [Debug] AWSSignature.m line:675 | -[AWSS3ChunkedEncodingInputStream getSignedChunk:] | AWS4 Chunked Header: [007fa5;chunk-signature=4dc07dfbf557576f4a3fcb0bd976a0a24a4202e8bc19605b65447d5ac5839909
]
2015-07-29 10:34:55.952 Constent[6229:586874] AWSiOSSDKv2 [Debug] AWSSignature.m line:653 | -[AWSS3ChunkedEncodingInputStream nextChunk] | stream read: 32677, chunk size: 32768
prog 0.066030182079586
total 130708
total 1979519
2015-07-29 10:35:01.379 Constent[6229:586874] AWSiOSSDKv2 [Debug] AWSSignature.m line:669 | -[AWSS3ChunkedEncodingInputStream getSignedChunk:] | AWS4 String to Sign: [AWS4-HMAC-SHA256-PAYLOAD
20150729T093445Z
20150729/eu-west-1/s3/aws4_request
4dc07dfbf557576f4a3fcb0bd976a0a24a4202e8bc19605b65447d5ac5839909
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
c90c101be69ea0bac00649e48734dc4b23c3aa81a914d71961f810a1d98fc640]
2015-07-29 10:35:01.381 Constent[6229:586874] AWSiOSSDKv2 [Debug] AWSSignature.m line:675 | -[AWSS3ChunkedEncodingInputStream getSignedChunk:] | AWS4 Chunked Header: [007fa5;chunk-signature=ecae7e66fbd9337aaf1063be3f8818293255ddc161e89c3fda929aecedb5d4f7
]
2015-07-29 10:35:01.382 Constent[6229:586874] AWSiOSSDKv2 [Debug] AWSSignature.m line:653 | -[AWSS3ChunkedEncodingInputStream nextChunk] | stream read: 32677, chunk size: 32768
prog 0.0825377275994825
total 163385
total 1979519

我还是不明白为什么它能如此可靠地粘在5 x 32k块上

可能发生了一些并发性问题。因为您将dispatch_sync用于dispatch_get_main_queue(),如果在块内阻塞了任何东西,则管理网络委托调用的队列可能会死锁。你应该确保在block中没有任何东西阻塞。另外,我将把dispatch_sync改为dispatch_async

在你的代码片段中有一些不相关的问题。您似乎正在为每个请求实例化一个新的服务客户端。这是非常低效的。您应该创建一个服务客户机实例,并尽可能重用它。

另外,您应该仔细检查CustomAmazonCredentialsProvider的实现。AWS临时凭据确实会过期,当它过期时,您的凭据提供程序应该响应- refresh,以便SDK可以检索一组新的凭据。通过符合AWSCredentialsProvider来实现您的凭据提供程序。以AWSWebIdentityCredentialsProviderAWSCognitoCredentialsProvider的实现为例。这个凭据提供程序应该:

  • 检索access key, secret keysession key从您的服务器。
  • 在本地持久化它们,直到它们过期。
  • 在被请求时返回凭据。
  • 如果过期,重新从服务器上检索它们。
  • - refresh被调用时启动凭据刷新进程。

我鼓励你看看Amazon Cognito Identity。使用Amazon Cognito,您可以通过使用公共登录提供商(如Amazon、Facebook、Google和任何OpenID Connect兼容的提供商)或使用您自己的用户身份系统,为访问AWS云服务创建唯一的最终用户标识符。它涵盖了许多TVM用例,并且更易于使用和管理。

最新更新