ios - 将 NSURLSessionDataTask 转换为具有后台支持的下载任务

标签 ios session download nsurlsession

我需要在检查标题(长度和类型)后使用后台功能下载某些文件(不是全部),但它必须在同一操作中,而不是创建新任务/请求(因为有时由于短时间内有很多连接,我从服务器收到错误)。 所以我开始任务:

NSURLSessionConfiguration *configuratione = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *sessione = [NSURLSession sessionWithConfiguration:configuratione delegate:self delegateQueue:nil];
NSURLSessionDataTask *datatask = [sessione dataTaskWithRequest:request];
[datatask resume];

然后,我知道可以在收到第一个响应时使用此委托(delegate)将数据任务转换为下载任务:

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
didReceiveResponse:(NSURLResponse *)response
 completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler
{
    if(XXXXXXXXXX){
        NSLog(@"transform into a download");
        completionHandler(NSURLSessionResponseBecomeDownload);
    }else{
        NSLog(@"Keep loading normally");
        completionHandler(NSURLSessionResponseAllow);
    }
}

但是,由于 Data Tasks 无法使用 BackgroundSessionConfiguration,我想新创建的下载将使用相同的默认 session 配置。 我怎样才能让下载在后台运行?有没有办法将它的 session 更改为后台 session ?或者应该采用哪种方法?

最佳答案

这个问题有点难以给出明确的答案,对我来说,所有 3 个主要的 URLLoading 因素( session 类型、任务类型、FG/BG 创建) 都受到您的设计的限制。 p>

由于 session 保留了配置的深拷贝(确定默认/背景/临时 session 性质类型),在启动您的 session 后(在我们的例子中:您的默认- type-Session) 您不能再修改当前 session 的配置对象。因此,如果您的设计不允许使新任务与新的(希望如此) BG 类型 session 相关联,则无法仅神奇地将“dataTask”转换为“downloadTask”。

请记住,NSURLSessionDataTaskNSURLSessionDownloadTask 都是 NSURLSessionTask 的子类,NSURLSessionDataTask 和 NSURLSessionDownloadTask 处理传入的响应数据 (分别为分段 VS 文件方式) 由框架实现的非常不同。

一个有吸引力的错觉可以是这个有吸引力的方法 URLSession:dataTask:didBecomeDownloadTask: ,但是你必须创建一个与当前 关联的新任务 (实际上是 DownloadTask)>(由您之前配置的默认类型深深打上烙印) session ,并将原始任务 (dataTask) 作为孤儿。我的理解是,由于额外创建了任务,您的设计不能采用此选项,而且您必须保留默认类型的 session 配置。

URLSession:dataTask:didBecomeDownloadTask: 真的应该命名为 URLSession:dataTask:wasReplacedByDownloadTask:

我现在唯一的简单解决方案是,在 Data-Task-Delegate (类实现 NSURLSessionDataDelegate 协议(protocol)) 接收 URLSession:dataTask:didReceiveData: 初始调用时,开始将这些分段数据存储在某种方式(存储到临时文件中,也许,模拟 NSURLSessionDownloadTask 的默认操作),并确保在 NSOperationQueue 上异步执行此委托(delegate) (我猜你的“后台能力”是指辅助线程,可以由 NSOperationQueue 下划线线程机制提供),直到下载完成,然后检查您的存储以获取累积结果(如果处理任何错误和/或将文件传输到其他地方) 在这个通用的 NSURLSessionTaskDelegate 方法中“URLSession:task:didCompleteWithError:”

这样做,您将请求(由 NSURLSessionDataTask 表示) 转换为下载(不是 NSURLSessionDownloadTask)。为了满足在后台队列上发生的这种转换,请为 (session/task) 这个委托(delegate)方法的最后一个参数提供一个非 nil 值: -- 否则,串行操作队列将无法满足您的“后台能力”需求

NSOperationQueue* aQueue = [[NSOperationQueue alloc] init];

NSURLSession *sessione = [NSURLSession sessionWithConfiguration:configuratione delegate:self delegateQueue: aQueue];

其他想法将手动执行多个 NSOperation 对象,覆盖它们的启动方法以确保异步执行您的下载任务,这可能有点棘手。

任何其他有更好解决方案的人,请带来更多 Spark ......或纠正我可能造成的任何误导。

关于ios - 将 NSURLSessionDataTask 转换为具有后台支持的下载任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23293166/

相关文章:

ios - UIImageView:将大小更改为图像大小?

ios - 知道 UICollectionView 是否在滚动

ios - 如何从字符串中识别 UTF-8 编码的文本并将其转换为 Swift 中的笑脸\表情符号

php - DataTables 1.9.4 - 限制结果

php - 如何根据 session 变量php从两个表中获取数据?

session - 使用 ajax 请求保持 session 事件是否安全?

flutter - 如何使用户从flutter应用程序下载/保存文件?

javascript - 如何从javascript下载文件

html - iOS 在多列中将 HTML 绘制为 PDF

objective-c - 当应用程序未激活时 iOS 后台下载