NSURLConnection的替代方案有哪些,用于分块传输编码?

10

我查阅了其他相关问题,但唯一的答案是“使用ASIHTTPRequest”,由于该项目已不再开发,我想问问人们正在使用哪些替代品。在开发SDK时,我们发现NSURLConnection在从服务器接收数据时会出现很多奇怪的行为。

我们追踪到这个问题是由于NSURLConnection无法很好地处理分块编码响应引起的。或者至少在这里读到的是这样: NSURLConnection 和“chunked”传输编码

我们与一些开发人员交流后得知,在iOS 5中情况有所改善,但我们需要确保我们的SDK向下兼容至少iOS 4.3。

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

到目前为止,我找到的所有替代品都基于NSURLConnection,我认为它们可能仍存在同样的缺陷。实际上,ASIHTTPRequest之所以有效是因为它位于比NSURLConnection更低的位置,但我们正在寻找其他替代方案,因为ASIHTTPRequest已不再受支持。

我们查看的其他库清单包括: Restkit, ShareKit, LRResty, AFNetworking, TTURLRequest

我知道这里有类似的问题 RESTKit是ASIHTTPRequest的好替代品吗? 和这里 ASIHTTPRequest的替代方案,但这两个解决方案都基于NSURLConnection。

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


还没有,我想先确认其他开发者是否遇到了类似的结果。我刚刚意识到我在问题中放错了链接。我本来是指这个链接 (http://stackoverflow.com/questions/8606493/nsurlconnection-and-chunked-transfer-coding)。我已经更新了帖子并提供了更多信息。 - pyr0manic
3个回答

19

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

  1. Define some props:

    NSMutableData * responseData;
    NSURLConnection * connection;
    
  2. Establish a 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];
    
  3. Register your callback method for connection established

    - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
         // You may have received an HTTP 200 here, or not...
         [responseData setLength:0];
    }
    
  4. Register your callback method for "chunk received"

    - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
        NSString* aStr = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
    
        NSLog(@"This is my first chunk %@", aStr);
    
    }
    
  5. Register your "connection finished" callback:

    - (void)connectionDidFinishLoading:(NSURLConnection *)connection {
       [connection release];
    }
    
  6. And finally, register you "connection failed" callback:

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

正如你所看到的,这很简单,你不需要使用任何其他框架。我每天都使用ASIHTTP,但对于分块传输编码,这已经足够了 :) - Carlos Ricardo
2
http://i3.kym-cdn.com/photos/images/newsfeed/000/150/505/f30fd24c56e1bcfc926883d6a51d5a00.gif - Carlos Ricardo
谢谢,我一旦有时间继续深入研究SDK时,会进行测试并确保将其设置为答案(如果有效)。 - pyr0manic

9

为了帮助下一个遇到不能使用 NSURLConnection 处理分块编码数据的人,我想提供一些帮助。

NSURLConnection 可以处理分块编码,但是它有一些未公开的内部行为。在打开连接之前,如果响应头中的 Content-Type 是 "text/html" 或 "application/octet-stream",它将先缓冲前 512 字节并让任何内容通过。至少在 iOS7 中是这样的。

然而,如果 Content-Type 设置为 "text/json",则不会缓冲响应。因此,无法使分块编码的 NSURLConnection 响应正常工作(即回调不被调用)的人应该检查响应头并在服务器上将其更改为 "text/json",如果这不会以某种其他方式破坏应用程序行为。


我不理解第二段中的逻辑:“如果Content-Type设置为"text/json",就不会缓冲响应,而且在服务器上将其更改为"text/json"似乎是矛盾的。难道你不想让NSURLConnection缓冲响应吗?如果不是,为什么不呢? - Gruntcakes
我不确定我理解你不理解什么,但我会重新表述一下:如果Content-Type不是text/json,它将被缓冲。这不是价值判断,我只是陈述行为。个人而言,我不希望它被缓冲,因为我无法控制的服务器没有设置text/json作为内容类型,导致响应(实际上并非json,而是自定义基于行的协议)未能到来。我不希望它被缓冲,因为应用逻辑和进一步操作取决于那512个字节中的某些内容永远不会到达。考虑“登录响应”或类似情况。 - maksa
@maksa text/json不是官方的MIME类型。你的评论同样适用于application/json吗? - Gruntcakes

2

我不知道有任何其他的替代方案。

所有其他的库都是建立在NSURLConnection之上的。虽然你可以使用其中一个非iOS库,例如libcurl。

ASIHTTPRequest是我所知道的唯一一个建立在CFNetworking层之上的库。这也许是原开发者停止开发它的主要原因——因为它不使用NSURLConnection,所以它有很多代码。

严格来说,说ASIHTTPRequest不再受支持可能并不正确。虽然原始开发者不再工作,但如果你查看github提交记录,你会看到其他人仍在继续开发它。很多人仍在使用它,出于各种原因,我也是其中之一。

说了这么多,回到你遇到的问题:我不确定一个三年前的帖子是否能成为证明一年前发布的NSURLConnection(即iOS 4.3)不支持分块传输的决定性参考。分块传输在Web上被广泛使用,似乎很难想象它会有如此大而明显的问题。有可能是你正在使用的服务器有非常特殊的问题导致了这个问题。


我同意,如果这仍然是一个严重的问题,我认为我会找到更多的信息。现在使用ASI意味着我们没有进一步探索它,但就在发布之前,我开始怀疑(因此寻求确认)。如果可能的话,最好使用NSURLConnection(代码库较小,不需要导入其他库等)。一旦我这样做了,我会确保更新此内容以供其他人参考。 - pyr0manic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接