在使用 Amazon iOS SDK 的 swift iOS 应用程序中,如何为 AWSS3TransferUtility 下载操作设置自定义超时?

Posted

技术标签:

【中文标题】在使用 Amazon iOS SDK 的 swift iOS 应用程序中,如何为 AWSS3TransferUtility 下载操作设置自定义超时?【英文标题】:In a swift iOS application that uses the Amazon iOS SDK, how to set a custom timeout to a AWSS3TransferUtility download operation? 【发布时间】:2019-04-25 20:12:47 【问题描述】:

我在 ios 12 的 swift 应用程序中使用 AWS SDK for iOS。我的应用程序必须列出 AWS S3 存储桶中的文件并下载其中一些文件。列表文件操作运行良好,我成功控制了它的超时。我没有成功完成下载任务。我的代码如下:

let credentialProvider = AWSCognitoCredentialsProvider(regionType: AWSRegionType.USEast1, identityPoolId: "<pool-id>")
let configuration = AWSServiceConfiguration(region: AWSRegionType.APSoutheast2, credentialsProvider: credentialProvider)

configuration?.timeoutIntervalForRequest = 30.0
configuration?.timeoutIntervalForResource = 86400


let transferUtilityConfiguration = AWSS3TransferUtilityConfiguration.init()

transferUtilityConfiguration.timeoutIntervalForResource = 86400
transferUtilityConfiguration.retryLimit = 1

AWSS3TransferUtility.register(with: configuration!, transferUtilityConfiguration: transferUtilityConfiguration, forKey: "com.mykey")

transferUtility = AWSS3TransferUtility.s3TransferUtility(forKey: "com.mykey")


let bucket = "com.mybucket"


transferUtility.configuration.maxRetryCount = 1

let urlForSavingFile = URL.init(fileURLWithPath: "")


transferUtility.download(to: urlForSavingFile, bucket: bucket, key: self.latestFileOnServer.key, expression: expression, completionHandler: self.completionHandler).continueWith  (task) -> AnyObject? in
            if let error = task.error 
                NSLog("Error: %@",error.localizedDescription);
                DispatchQueue.main.async(execute: 
                    statusLabel.text = "Failed"
                )
            

            if let _ = task.result 

                self.refDownloadTask = task.result
                self.refDownloadTask?.setCompletionHandler(self.completionHandler!)
                methodStart = Date.init()

                let formatter = DateFormatter.init()

                formatter.dateFormat = "dd' 'MMM' 'YYYY' - 'HH:mm:ss"
                formatter.locale = Locale.init(identifier: "Europe / Rome")
                let italyDate = formatter.string(from: methodStart)

                print("Download started at \(italyDate)")
                DispatchQueue.main.async(execute: 
                    //statusLabel.text = "Downloading..."
                )
                NSLog("Download Starting!")
                // Do something with uploadTask.
            
            return nil;
        

如果我等待文件完成下载,则会正确调用完成处理程序,但如果我使用网络链接调节器关闭网络,则传输将永远挂起,并且永远不会调用完成处理程序。任何帮助深表感谢。谢谢

【问题讨论】:

在这里报告同样的问题。我的与上传有关,而不是下载,但似乎不遵守超时,如果达到超时,则永远不会调用完成处理程序。 您好,我提供了一个解决方案,感谢您的评论,请告诉我它是否适合您。谢谢 【参考方案1】:

经过多次测试,我成功找到了解决方案,并使 SDK 尊重超时。在我的测试中,最初,我对命名约定有点困惑:

timeoutIntervalForResource 是传输可以花费的最长时间,无论成功/失败。这与 AWS 开发工具包开箱即用。

timeoutIntervalForRequest是我们感兴趣的值。它是网络丢失后任务等待额外数据的时间间隔。它的计时器是从收到最后一个数据包开始安排的。正如您在问题和 cmets 中看到的那样,AWS SDK 似乎不尊重它。

此命名约定与 Apple Cocoa USURLSession 系列类相同。在我的研究过程中,我遇到了这个answer。对于将其配置实例化为后台配置的 URLSession,似乎这种行为一直存在。这不是不当行为,它只是 iOS 8 以来后台下载的新标准。

现在,解决方案。通过在 AWS SDK Objective-C 代码中进行调试(是的,他们提供了完整的代码),我找到了位置。如果你打开 AWSS3TransferUtility.m 文件,在第 400 行,你会发现,在这个方法中:

- (instancetype)initWithConfiguration:(AWSServiceConfiguration *)serviceConfiguration
     transferUtilityConfiguration:(AWSS3TransferUtilityConfiguration *)transferUtilityConfiguration
                       identifier:(NSString *)identifier
                completionHandler: (void (^)(NSError *_Nullable error)) completionHandler 

那些陈述:

//Create the NS URL session
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:_sessionIdentifier];
configuration.allowsCellularAccess = serviceConfiguration.allowsCellularAccess;
configuration.timeoutIntervalForResource = transferUtilityConfiguration.timeoutIntervalForResource;

为了使它起作用,请将第一条语句替换为:

NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];

现在,在您的代码中:

let credentialProvider = AWSCognitoCredentialsProvider(regionType: AWSRegionType.USEast1, identityPoolId: "<pool-id>")
let configuration = AWSServiceConfiguration(region: AWSRegionType.APSoutheast2, credentialsProvider: credentialProvider)

configuration?.timeoutIntervalForRequest = 30.0
configuration?.timeoutIntervalForResource = 86400

SDK 将在网络丢失 30 秒后触发完成处理程序并返回 -1001 错误。

我只测试了传输实用程序下载任务,但它也应该适用于上传。 我知道这个解决方案不是防弹的,因为它没有考虑会话配置标识符,但我会继续努力。此外,该解决方案意味着更改 AWS 开发工具包代码,但只需要一行代码。更改只是使 AWSS3TransferUtility 创建标准 URLSessionConfigurations 而不是后台的。这可能还有其他副作用需要考虑。

【讨论】:

以上是关于在使用 Amazon iOS SDK 的 swift iOS 应用程序中,如何为 AWSS3TransferUtility 下载操作设置自定义超时?的主要内容,如果未能解决你的问题,请参考以下文章

是否可以使用 iOS SDK 更改 Amazon Cognito 中的用户名?

在iOS Swift中不使用AWS SDK在Amazon S3存储桶中上传的背景图像(背景模式)

在 swift 项目中导入 PayPal-iOS-SDK

在使用 Amazon iOS SDK 的 swift iOS 应用程序中,如何为 AWSS3TransferUtility 下载操作设置自定义超时?

Amazon S3 iOS SDK 照片上传有时会出错 - SignatureDoesNotMatch

amazon s3 iphone sdk 下载图片