如何从 NSURLSessionDownloadTask downloadTaskWithRequest 获得响应

How to get a response from NSURLSessionDownloadTask downloadTaskWithRequest

先介绍一下背景: 应用程序应该从 AWS S3 服务器获取文件。为此,该过程的第一步是转到本地服务器并从中获取文件名和其他一些信息。在那一步之后,我们有一个完整的 URLMutableRequest.

注意:我正在将 NSURLSession 设置为后台会话:

- (NSURLSession *)backgroundSession
{
    static NSURLSession *session = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration backgroundSessionConfiguration:@"identifier"];
        session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:nil];
    });
    return session;
}

这是从 AWS S3 服务器下载文件的任务:

对于此任务我想在后台模式下使用委托 运行。

@property (nonatomic, strong) NSURLSessionDownloadTask *downloadTask;
@property (nonatomic, strong) NSURLSession *defaultSession; 

self.defaultSession = [self backgroundSession];
self.downloadTask = [self.defaultSession downloadTaskWithRequest:request];
[self.downloadTask resume];

如何从这个请求中得到响应?

Apple 文档说在使用 backgroundSessionConfiguration.

时不能将块作为 completionHandler

您需要在 class 中实施 NSURLSessionDownloadDelegate 协议(因为您将会话委托指定为 self)。

您应该查看文档以了解可用的方法,但您至少要实现以下内容:

- (void)URLSession:(NSURLSession *)session didBecomeInvalidWithError:(NSError *)error
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data

NSURLSessionDownloadTask 有一个 response 属性(其基数 class、NSURLSessionTask 的一部分)应该设置为响应。参见 here

如果有人想知道如何在下载完成之前获取下载响应,请尝试以下操作:改为启动 dataTask,获取响应,然后在需要时将 dataTask 转换为下载。

NSURLSessionTask *task = [session dataTaskWithRequest:request];
[task resume];

NSURLSessionDataDelegate

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler {
    // use response, convert data task to download task
    completionHandler(NSURLSessionResponseBecomeDownload);
}

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didBecomeDownloadTask:(NSURLSessionDownloadTask *)downloadTask {
    // downloadTask converted from dataTask
}

NSURLSessionDownloadDelegate

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {
    // update progress
}

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location {
    // copy downloaded file from location
}