我正在调查使用NSURLSessionUploadTasks来管理几个文件的后台上传。会话使用以下方式创建:
_urlsession = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration backgroundSessionConfiguration:identifier] delegate:self delegateQueue:nil];
这是在符合URLSessionDataTaskDelegate
的类中创建的,具体定义:
– URLSession:dataTask:didReceiveResponse:completionHandler:
– URLSession:dataTask:didBecomeDownloadTask:
– URLSession:dataTask:didReceiveData:
每次调用其中一个委托时,都会记录到控制台。
然后,使用以下代码创建上载任务:
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';
但是,我得到的委托回调序列并不像预期的那样:
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
委托回调,事先没有didReceiveResponse
回调。这对我来说是一个意外的行为:我希望收到有关响应的信息,以便我可以正确设置数据,或者更好的是,将任务转换为下载任务以将响应保存到文件中。
如果在默认URL会话中提交上载任务,则调用didReceiveResponse,我可以成功将任务转换为后台下载任务。
我在Apple的文档中找不到任何关于didReceiveResponse
是否应该在后台调用NSURLSessionUploadTask
的指示。 似乎他们应该:NSURLSessionUploadTask
的文档表明它是NSURLSessionDataTask
的子类,行为有很小的修改,但列出的差异都没有涉及不发送{ {1}}回调。没有任何特定于后台会话的文档提到此限制。
这是一个错误,还是错过/误解了某些文档,说明后台的上传任务不会调用didReceiveResponse
?
答案 0 :(得分:6)
在最近的技术会谈中,我向Apple工程师询问过这个问题。他们跟进并给出了以下响应 - 并不完全令人满意,如果它与任何其他HTTP处理流程不同,我觉得他们应该记录这种行为。特别是因为前景行为确实获得了didReceiveData,但没有获得didReceiveResponse。他们至少需要记录这种非显而易见的行为。
“今天的工作方式是我们不会为后台上传发送didReceiveResponse回调,以避免在应用程序尚未运行时唤醒应用程序。缺点是应用程序无法选择将后台上传转换为下载任务当收到响应时。我们的决定是基于期望文件上传的响应数据很小,因此将响应数据传递给客户端,因为NSData而不是下载的文件就可以了。“