我正在研究使用 NSURLSessionUploadTasks 来管理一些文件的后台上传。 session 是使用以下方法创建的:
_urlsession = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration backgroundSessionConfiguration:identifier] delegate:self delegateQueue:nil];
这是在符合
URLSessionDataTaskDelegate
的类中创建的。 ,并具体定义:– URLSession:dataTask:didReceiveResponse:completionHandler:
– URLSession:dataTask:didBecomeDownloadTask:
– URLSession:dataTask:didReceiveData:
并在每次调用这些委托(delegate)之一时登录到控制台。
然后,使用以下代码创建上传任务:
NSString *urlString = [NSString stringWithFormat:@"%@%@?filename=%@", HOST, UPLOAD_PATH, filename];
NSMutableURLRequest *attachmentUploadRequest = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlString]];
attachmentUploadRequest.HTTPMethod = @"POST";
[attachmentUploadRequest addValue:@"application/binary" forHTTPHeaderField:@"Content-Type"];
NSURLSessionTask* task = [_urlsession uploadTaskWithRequest:attachmentUploadRequest fromFile:filePath];
task.taskDescription = 'upload';
但是,我得到的委托(delegate)回调序列并不像预期的那样:
URLSession:didReceiveChallenge:completionHandler:]:196: Respond with <NSURLCredential: 0x1cf4fe00>:
URLSession:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:]:282: Task 'upload' sent 32768 bytes
URLSession:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:]:282: Task 'upload' sent 48150 bytes
URLSession:dataTask:didReceiveData:]:222: Task 'upload' got some data:
值得注意的是,正文数据按预期发送,但随后立即切换到
didReceiveData
委托(delegate)回调,没有 didReceiveResponse
提前回调。这对我来说是一个意外的行为:我希望收到有关响应的信息,以便我可以正确设置数据,或者更好的是,将任务转换为下载任务以将响应保存到文件中。如果上传任务在默认 URL session 中提交,则调用 didReceiveResponse,我可以成功地将任务转换为后台下载任务。
我在 Apple 的文档中找不到任何关于是否
didReceiveResponse
的迹象。应调用 NSURLSessionUploadTask
s 在后台。他们似乎应该:NSURLSessionUploadTask
的文档表示它是 NSURLSessionDataTask
的子类在行为上稍作修改,但列出的差异均不涉及不发送 didReceiveResponse
打回来。没有一个特定于背景 session 的文档提到这个限制。这是一个错误,还是错过/误解了一些解释后台上传任务不调用
didReceiveResponse
的文档?
最佳答案
在最近的技术讲座中,我向苹果工程师询问了这个问题。他们跟进并给出了以下响应 - 并不完全令人满意,我觉得如果它与任何其他 HTTP 处理流程不同,他们应该记录这种行为。特别是因为前台行为确实获得了 didReceiveData,但没有获得 didReceiveResponse。至少他们需要记录这种不明显的行为。
“今天的工作方式是,我们不会为后台上传发送 didReceiveResponse 回调,以避免在应用尚未运行时唤醒应用。缺点是应用无法选择在响应时将后台上传转换为下载任务收到。我们的决定是基于预期文件上传的响应数据会很小,因此将响应数据作为 NSData 而不是下载的文件传递给客户端就可以了。
关于delegates - 是否应该始终为具有自定义委托(delegate)的 NSURLSessionUploadTasks 调用 didReceiveResponse?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19149051/