Mulipartpost NSURLConnection over 3G 网络问题

Posted

技术标签:

【中文标题】Mulipartpost NSURLConnection over 3G 网络问题【英文标题】:Mulipartpost NSURLConnection over 3G network problems 【发布时间】:2013-06-03 18:05:31 【问题描述】:

我们有一个 ios 应用程序,它使用多部分帖子将图像上传到服务器。使用 wifi 时一切正常,但在 3G 上拍摄大图像时出现网络错误。

在客户端 (iPhone) 上:

我有一个

Domain=NSURLErrorDomain Code=-1021 “请求体流耗尽”

基于this post,我尝试将AFNetwork 库与该方法一起使用,但仍然得到了完全相同的结果。

在服务器上:

我已经设置了一个代理来查看请求,我得到了

“插座断管”

通常在传输完 740Kb 之后

那么,我做错了什么?就像我说的那样,在 wifi 上一切正常,在 3G 上,小图像也很好。

AFNetwork 版本代码(大图像在 600 - 800 kb 后停止传输):

AFHTTPClient *client = [[AFHTTPClient alloc] initWithBaseURL:self.baseURL];

        request = [client multipartFormRequestWithMethod:@"POST"
                                                                         path:nil
                                                                   parameters:nil
                                                    constructingBodyWithBlock:^(id<AFMultipartFormData> formData)
                                        

                                            for (NSString* partType in self.parts) 
                                                if ([partType isEqualToString:@"jsonpart"]) 
                                                    [formData appendPartWithFormData:[self.parts objectForKey:partType] name:@"@json"];
                                                
                                                else //is an image for sure
                                                    [formData appendPartWithFileData:[self.parts objectForKey:partType]
                                                                                name:partType
                                                                            fileName:[NSString stringWithFormat:@"%@-%d.jpg", partType, [partType hash]]
                                                                            mimeType:@"image/jpeg"];
                                                

                                            

                                            [formData throttleBandwidthWithPacketSize:kAFUploadStream3GSuggestedPacketSize delay:kAFUploadStream3GSuggestedDelay];
                                        ];

        AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];

        [client enqueueHTTPRequestOperation:operation];

【问题讨论】:

您的移动运营商是什么?另外,您是否尝试使用低于默认推荐值的throttleBandwidthWithPacketSize:delay: 是的,我确实试过那个。不同的运营商也会出现同样的问题。 【参考方案1】:

澄清错误的含义以及错误的来源:

当请求已设置 HTTPBodyStream 和 Content-Length 标头明确设置,并且输入流未提供与 Content-Length 标头中指定的一样多的字节时,您会收到此错误。也就是说,底层连接在从输入流中读取指定数量的字节之前就从输入流中获得了 EOF。

因此,原因可能是多部分正文的内容长度计算不正确。这很有可能,因为计算多部分的长度很容易出错。

如果您收到重定向响应并且输入流已经打开并且可能已经读取了一些数据,也会发生错误。重定向响应要求输入流将“倒带”,以便在收到正确响应时可以从头开始读取。这不会自动发生,必须在委托中显式实现。 (看看 AFNetworking 是否会在重定向的情况下以某种方式“倒回”输入流 - 这就是 connection:needNewBodyStream: 是否已实现)。

我怀疑,当运行循环中存在一些微妙的死锁时,也可能会发生错误,这会阻止连接读取流 - 或流从其源中读取。

也可能发生,这个错误是另一个错误的副作用 - 这个错误掩盖了原来的错误。

也可能是这样,在 AFNetworking 中用于完成多部分表单请求的 NSInputStream 的内部子类存在错误。恕我直言,实现有点可疑,在其他地方肯定存在关于流的潜在错误。

【讨论】:

但如果是这样的话,怎么可能在 wifi 上工作,但在 3G 上却不能使用完全相同的代码? 好问题!答案可能在数据包跟踪中找到,该跟踪将数据包作为中间人嗅探。但首先我会检查委托方法 connection:needNewBodyStream: 是否已被调用(可能是身份验证挑战的结果),以及请求的 HTTPBodyStream 是否会被网络库重置。 您还可以检查,如果您使用 NSData(通过属性 HTTPBody)而不是流设置请求,请求是否可以工作。由于 NSData 可以通过内部连接“倒带”,因此当身份验证质询导致请求重新发送时,没有问题。请注意,这一切都可能透明地发生,因此您应该使用调试器和数据包跟踪进行检查。 在我使用模拟器的情况下,如果每次都失败,除非我一次发送两个上传请求。然后都成功并且任何后续的单个上传也成功,直到我下次启动模拟器。有什么想法吗?【参考方案2】:

好的,在花了很多时间之后,我终于明白了。与代码无关,出于某种原因公司防火墙在这里发挥了作用。关闭防火墙后一切正常。奇怪,但这解决了它,并且超出了 iOS 或代码范围。

【讨论】:

你是如何关闭设备上的防火墙的? 不,我指的是保护我发送数据的公司服务器的防火墙。在这样做之后,每一个在工作之前失败的测试。 好的。这是什么服务器?如果它是 Rails 应用程序,其他人报告说禁用“protect_from_forgery”对这里有帮助ruby.about.com/od/mr/g/protectforgery.htm>。纯 API 控制器不需要此防止 CSFR 攻击的安全标志,而仅适用于服务 html 页面的控制器。其他 Web 服务器应用程序可能具有类似的机制。请重新启用防火墙! ;)

以上是关于Mulipartpost NSURLConnection over 3G 网络问题的主要内容,如果未能解决你的问题,请参考以下文章

使用 AFNetworking 未获得完整的响应标头

无法确定当前国家代码:错误域=NSURLErrorDomain 代码=-1005 “网络连接丢失。”

2016 - 1 - 25 第三方网络框架 AFN的简单使用

IOS网络篇1之截取本地URL请求(NSURLProtocol)