Alf*_*uro 1 amazon-s3 ios swift
我在 iOS 12 的 swift 应用程序中使用适用于 iOS 的 AWS 开发工具包。我的应用程序必须列出 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;
}
Run Code Online (Sandbox Code Playgroud)
如果我等待文件完成下载,则会正确调用完成处理程序,但如果我使用网络链接调节器关闭网络,则传输将永远挂起,并且永远不会调用完成处理程序。任何帮助深表感谢。谢谢
经过多次测试,我成功找到了解决方案,让SDK尊重超时。在我的测试过程中,最初,我对命名约定有点困惑:
timeoutIntervalForResource是传输可以花费的最长时间,无论成功/失败。这可以通过 AWS SDK 开箱即用。
timeoutIntervalForRequest是我们感兴趣的值。它是任务在网络丢失后等待额外数据的时间间隔。它的计时器是从最后一个收到的数据包开始安排的。正如您在问题和评论中所读到的那样,AWS SDK 似乎没有遵守这一点。
此命名约定与 Apple Cocoa USURLSession 类系列相同。在我的研究过程中,我发现了这个答案。看来,对于将其配置实例化为后台配置的 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 {}
Run Code Online (Sandbox Code Playgroud)
这些陈述:
//Create the NS URL session
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:_sessionIdentifier];
configuration.allowsCellularAccess = serviceConfiguration.allowsCellularAccess;
configuration.timeoutIntervalForResource = transferUtilityConfiguration.timeoutIntervalForResource;
Run Code Online (Sandbox Code Playgroud)
为了使其工作,请将第一条语句替换为:
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
Run Code Online (Sandbox Code Playgroud)
现在,在您的代码中:
let credentialProvider = AWSCognitoCredentialsProvider(regionType: AWSRegionType.USEast1, identityPoolId: "<pool-id>")
let configuration = AWSServiceConfiguration(region: AWSRegionType.APSoutheast2, credentialsProvider: credentialProvider)
configuration?.timeoutIntervalForRequest = 30.0
configuration?.timeoutIntervalForResource = 86400
Run Code Online (Sandbox Code Playgroud)
网络丢失 30 秒后,SDK 将触发完成处理程序并显示 -1001 错误。
我只在 Transferutilitydownload 任务上进行了测试,但它也应该适用于上传。我知道这个解决方案不是防弹的,因为它没有考虑会话配置标识符,但我会努力解决它。此外,该解决方案意味着更改 AWS SDK 代码,但只更改一行代码。此更改只是使 AWSS3TransferUtility 创建标准 URLSessionConfigurations 而不是后台配置。这可能还有其他副作用需要考虑。
| 归档时间: |
|
| 查看次数: |
1511 次 |
| 最近记录: |