用于分块传输编码的 NSURLConnection 的替代方法是啥

Posted

技术标签:

【中文标题】用于分块传输编码的 NSURLConnection 的替代方法是啥【英文标题】:What are alternatives to NSURLConnection for chunked transfer encoding用于分块传输编码的 NSURLConnection 的替代方法是什么 【发布时间】:2012-03-06 23:05:35 【问题描述】:

我已经检查了与此相关的其他问题,但唯一的答案是“使用ASIHTTPRequest”,因为它不再正在开发中NSURLConnection 从服务器接收数据时出现很多奇怪的行为。

我们追查到NSURLConnection 不能很好地处理分块编码中的响应这一事实。或者至少我们在这里看到了这个问题NSURLConnection and "chunked" transfer-coding

我们交谈过的一些开发人员说它在 ios 5 中变得更好,我们需要确保我们的 SDK 至少向后兼容 iOS 4.3。

我想确认这实际上是 NSURLConnection 中的一个问题,以及人们如何处理它。

到目前为止,我发现的所有替代方案都基于NSURLConnection,我假设这样会有相同的缺陷。 ASIHTTPRequest 确实有效,因为它的基础比 NSURLConnection 低一点,但在它不再受支持的情况下正在寻找替代方案。

查看的其他库列表如下: Restkit, ShareKit, LRResty, AFNetworking, TTURLRequest

我知道Is RESTKit a good replacement for ASIHTTPRequest? 和ASIHTTPRequest alternative 这里有类似的问题,但是这两种解决方案都基于 NSURLConnection。

编辑:我注意到我在帖子开头指出了错误的问题,所以更新了。它指向 2008 年的一个帖子,我见过类似的帖子,但没有一个是最近的。

【问题讨论】:

还没有,我想检查一下其他开发人员是否也看到了类似的结果。我刚刚意识到我在我的问题中放置了错误的链接。我的意思是(***.com/questions/8606493/…)。我已经用更多信息更新了帖子。 【参考方案1】:

NSURLConnection 支持分块传输。我使用它们。

    定义一些道具:

    NSMutableData * responseData;
    NSURLConnection * connection;
    

    建立连接

    NSURL *url = [NSURL URLWithString:@"...."];
    self.responseData = [[NSMutableData alloc] initWithLength:0] ;
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    self.connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
    

    注册您的回调方法以建立连接

    - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response 
         // You may have received an HTTP 200 here, or not...
         [responseData setLength:0];
    
    

    为“收到的块”注册你的回调方法

    - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data 
        NSString* aStr = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
    
        NSLog(@"This is my first chunk %@", aStr);
    
    
    

    注册您的“连接完成”回调:

    - (void)connectionDidFinishLoading:(NSURLConnection *)connection 
       [connection release];
    
    

    最后,注册“连接失败”回调:

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error 
    NSLog(@"Something went wrong...");

【讨论】:

如您所见,这很简单,您不需要使用任何其他框架。我每天都使用 ASIHTTP,但是对于分块传输编码,这就足够了 :) i3.kym-cdn.com/photos/images/newsfeed/000/150/505/… 谢谢,一旦我有时间再次深入研究 SDK,我会对此进行测试,如果可行,我会确保将其设置为答案。【参考方案2】:

只是为了提醒下一个到达这里但仍然无法让 NSURLConnection 处理块编码数据的人。

NSURLConnection 将使用分块编码,但具有未公开的内部行为,因此它将在打开连接之前缓冲前 512 个字节,并通过响应标头中的 IF Content-Type 为“text/html”,或“应用程序/八位字节流”。这至少适用于 iOS7。

但是,如果 Content-Type 设置为“text/json”,它不会缓冲响应。因此,任何无法获得分块编码的 NSURLConnection 响应(即不调用回调)的人都应该检查响应标头并将其在服务器上更改为“text/json”,如果它不会以其他方式破坏应用程序行为.

【讨论】:

我不明白第二段中的逻辑“如果 Content-Type 设置为“text/json”和“并在服务器上将其更改为”文本,它不会缓冲响应/json”似乎是矛盾的。您不希望 NSURLConnection 缓冲响应吗?如果没有,为什么不呢? 我不确定我是否理解您不理解的内容,但我会改写一下:如果 Content-Type 不是 text/json,它将被缓冲。这不是价值判断,我只是在陈述行为。就我个人而言,我不希望它缓冲,因为我无法控制的服务器没有将 text/json 设置为内容类型,导致响应(实际上不是 json,而是基于自定义行的协议)不来。我不希望它被缓冲,因为应用程序逻辑和进一步的操作取决于那些永远不会出现的 512 字节内的东西。想想“登录响应”或类似的东西。 @maksa text/json 不是官方的 MIME 类型。您的 cmets 是否同样适用于 application/json?【参考方案3】:

我知道没有任何替代方案。

所有其他库都建立在 NSURLConnection 之上。尽管您可以使用其中一个非 iOS 库,例如。 libcurl.

ASIHTTPRequest 是我所知道的唯一一个构建在 CFNetworking 层之上的库。这是(可能是间接的)原始开发人员停止开发它的主要原因 - 因为它不使用 NSURLConnection 它有 很多 代码。

说不再支持 ASIHTTPRequest 可能并不完全正确。确实,原来的开发者不再在它上面工作,但是如果你查看 github 提交,你会发现它仍在被其他人处理。很多人仍在使用它,出于各种原因,包括我自己。

说了这么多,回到你遇到的问题:我不确定一个 3 岁的线程是否一定是证明 NSURLConnection 的 1 岁版​​本(即 iOS 4.3)没有的权威参考' t 支持分块传输。分块传输在网络上被大量使用,以至于它似乎不太可能出现如此大而明显的问题。您正在使用的服务器可能有一些非常特殊的东西导致了问题。

【讨论】:

我同意,如果这仍然是一个严重的问题,我想我会发现更多。现在使用 ASI 意味着我们没有进一步探索它,但在发布之前我会开始怀疑(因此寻找确认)。当我有机会时,我可能会回去看看它,因为如果可能的话,最好使用 NSURLConnection (不需要导入较小的代码库和库等)一旦我这样做,我会确保为其他想知道的人更新此内容。

以上是关于用于分块传输编码的 NSURLConnection 的替代方法是啥的主要内容,如果未能解决你的问题,请参考以下文章

HTTP协议之chunk编码(分块传输编码)

jQuery 和传输编码分块

分块传输编码 - 浏览器行为

标头传输编码:分块并请求为空

禁用传输编码:在 Spring Webflux 响应中分块

以分块传输编码发送的响应,并指示在某些数据已发送后发生的错误