我在一个适用于iOS 12的swift应用程序中使用AWS SDK for iOS。我的应用程序必须列出亚马逊网络服务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;
}如果我等待文件完成下载,则正确地调用完成处理程序,但如果我使用网络链接调节器关闭网络,则传输将永远挂起,并且永远不会调用完成处理程序。任何帮助都是非常感谢的。谢谢
发布于 2019-04-28 06:07:45
经过几次测试,我成功地找到了解决方案,并使SDK遵守超时。在我的测试中,最初,我对命名约定感到有点困惑:
timeoutIntervalForResource是传输可以花费的最长时间,无论是否成功/失败。这可以通过AWS SDK开箱即用。
timeoutIntervalForRequest是我们感兴趣的值。它是任务在网络丢失后等待额外数据的时间间隔。它的计时器是从最后一个接收到的数据包开始调度的。正如您在问题和评论中看到的那样,AWS SDK似乎没有遵守这一点。
此命名约定与Apple Cocoa USURLSession类家族相同。在我的研究过程中,我偶然发现了这个answer。对于将其配置实例化为后台配置的URLSessions,似乎已经一致地经历了这种行为。这不是一种不当行为,它只是从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 = 86400SDK将在网络丢失30秒后触发完成处理程序,并返回-1001错误。
我只在一个传输实用程序的下载任务上进行了测试,但它在上传时也应该可以工作。我知道这个解决方案不是万无一失的,因为它没有考虑会话配置标识符,但我会努力解决它。此外,该解决方案还意味着更改AWS SDK代码,但只需更改一行代码。这一更改只是让AWSS3TransferUtility创建标准URLSessionConfigurations,而不是后台The。这可能还有其他要考虑的副作用。
https://stackoverflow.com/questions/55856944
复制相似问题