在 iOS8 中使用 NSUrlSession 使用流请求进行后台上传

Posted

技术标签:

【中文标题】在 iOS8 中使用 NSUrlSession 使用流请求进行后台上传【英文标题】:Background Upload With Stream Request Using NSUrlSession in iOS8 【发布时间】:2015-02-04 06:49:23 【问题描述】:

之前在 ios7 中,当我们尝试在后台使用流请求上传时,会出现以下异常

由于未捕获的异常“NSGenericException”而终止应用,原因:“后台会话中的上传任务必须来自文件”

但在 iOS8 中,当我们尝试在后台使用流上传时也不例外。

现在我的问题是

1) iOS8 中是否允许使用 uploadTaskWithStreamedRequest: 进行 backgourd 上传?

2) 在 iOS8 中,我使用带有 uploadTaskWithStreamedRequest 的后台 NSURLConfiguration。我正在使用 -(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task needNewBodyStream:(void (^)(NSInputStream *))completionHandler 向 NSUrlSession 提供流。当应用程序处于前台时,它工作正常并将我的文件上传到服务器。但是一旦应用程序在后台运行,流就会结束并且 NSURLSession 完成并出现以下错误

Error Domain=NSURLErrorDomain Code=-997 "失去与后台传输服务的连接"

我认为当应用程序进入后台时,我的流会结束。现在我的问题是我应该在哪个 runloop 中安排我的 Stream 或者让我知道我的理解是否有任何错误。

-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task needNewBodyStream:(void (^)(NSInputStream *))completionHandler

    // Open producer/consumer streams.  We open the producerStream straight
    // away.  We leave the consumerStream alone; NSURLConnection will deal
    // with it.
    NSLog(@"%@", [NSThread currentThread]);
    NSInputStream *consStream;
    NSOutputStream *prodStream;
    [NSStream createBoundInputStream:&consStream outputStream:&prodStream bufferSize:SFAMaxBufferLength];
    assert(consStream != nil);
    assert(prodStream != nil);
    self.consumerStream = consStream;
    self.producerStream = prodStream;
    self.producerStream.delegate = self;
    [self.producerStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
    [self.producerStream open];
    // Set up our state to send the body prefix first.
    self.buffer = [self.bodyPrefixData bytes];
    self.bufferLimit = [self.bodyPrefixData length];
    completionHandler(self.consumerStream);

【问题讨论】:

【参考方案1】:

您无法使用后台配置上传流式任务。我只在两种情况下成功上传数据:

    使用存储在请求正文中的数据下载任务。 从文件上传任务。在这种情况下,您将不会收到响应正文。

【讨论】:

如果您可以共享任何文档链接以指出 backgroundTask 仅支持从文件上传而不支持从正文或 NSStream 上传,那就太好了? 不幸的是,他们没有记录很多关于后台传输的内容。我之所以知道这些,是因为我们做了很多研究。【参考方案2】:

您可以在后台上传多部分文件 - 只是这不是直截了当的。参考:AFNetworking error in uploadTaskWithStreamedRequest

【讨论】:

请注意 link-only answers 是不鼓励的,所以答案应该是寻找解决方案的终点(而不是另一个参考中途停留,随着时间的推移往往会变得陈旧)。请考虑在此处添加独立的概要,保留链接作为参考

以上是关于在 iOS8 中使用 NSUrlSession 使用流请求进行后台上传的主要内容,如果未能解决你的问题,请参考以下文章

iOS8:NSURLSession:NSURLSessionDataTask '客户端在收到整个响应之前关闭连接'

如何使用 Alamofire(或 NSUrlSession)使调试日志静音?

NSURLSession 的 IOS9 SSL 错误

NSURLSession学习笔记简介

NSURLSession学习笔记简介

Popover 演示在 iOS8 中不会使 tintColor 变暗