2013-06-07 1 views
1

У нас есть приложение iOS, которое загружает изображения на сервер с помощью многостраничного сообщения. Все в порядке при использовании Wi-Fi, но в 3G для больших изображений мы получаем сетевые ошибки.Mulipartpost NSURLConnection через проблемы с сетью 3G

На клиенте (iPhone):

Я получил

Домен = NSURLErrorDomain Code = -1021 «потока тело запроса исчерпала»

на основе this post я попытался использовать библиотеку AFNetwork с этим методом, но все же получить тот же точный результат.

На сервере:

У меня есть настройки прокси, чтобы увидеть запрос, и я получаю

«Гнездо сломанной трубы»

обычно после 740Kb были переданы

Итак, что я делаю неправильно? Как я уже говорил, Wi-Fi работает нормально, а на 3G с маленькими изображениями тоже хорошо.

версия кода AFNetwork (прекращает передачу после 600 - 800 кб для больших изображений):

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]; 
+0

Ваш мобильный оператор? Кроме того, вы пытались использовать 'throttleBandwidthWithPacketSize: delay:' с более низкими значениями, чем рекомендуемые значения по умолчанию? –

+0

Да, я попробовал это. Такая же проблема возникает и для разных носителей. – Emilio

ответ

0

Ok, после долгих часов, проведенных на этом я, наконец, получил его. Ничего общего с кодом, по какой-то причине брандмауэр компании играет здесь роль. Когда брандмауэр выключен, все работает нормально. Странно, но это решает его и выходит за рамки iOS или кода.

+0

Как вы отключили брандмауэр на устройстве? – CouchDeveloper

+0

Нет, я имел в виду межсетевой экран, который защищает сервер компании, где я отправлял данные. После этого каждый тест, который был неудачным, только что сработал. – Emilio

+0

ОК. Что это за сервер? Если это приложение Rails, другие сообщили, что здесь отключено «protect_from_forgery» . Этот флаг безопасности, который предотвращает атаки CSFR, не требуется для чистых контроллеров API, но только для контроллеров, обслуживающих HTML-страницы. Другие приложения веб-сервера могут иметь аналогичный механизм. Пожалуйста, включите брандмауэр снова! ;) – CouchDeveloper

2

разъяснение того, что означает, что ошибка, и где она может исходить от:

Вы получаете эту ошибку, когда запрос был настроен с HTTPBodyStream и заголовок Content-Length явно, и входной поток не укажите столько байтов, сколько указано в заголовке Content-Length. То есть, подстилающее соединение получило EOF из входного потока, прежде чем указанное количество байтов могло быть прочитано из потока.

Таким образом, причиной может быть некорректно рассчитанная длина содержимого многочастного тела. Это вполне вероятно, так как вычисление длины многопроцессора довольно подвержено ошибкам.

Ошибка также возникает, если вы получили ответ перенаправления, и входной поток уже открыт и, возможно, некоторые данные были прочитаны. Ответ перенаправления требует, чтобы входной поток был «перемотан», чтобы его можно было прочитать с самого начала, когда будет получен правильный ответ. Это происходит не автоматически, и это должно быть явно реализовано в делегате. (Посмотрите на AFNetworking, будет ли он «перематывать» входной поток каким-то образом в случае перенаправления - то есть реализуется ли connection:needNewBodyStream:).

Возможно, я подозреваю, что ошибка может произойти и при наличии некоторой тонкой мертвой блокировки в цикле запуска, которая препятствует соединению читать поток - или поток для чтения из его источников.

Возможно также, что эта ошибка является побочным эффектом другой ошибки - и эта ошибка маскирует исходную.

Возможно также, что внутренний подкласс NSInputStream, который используется для выполнения запроса многочастной формы в AFNetworking, имеет ошибку. IMHO реализация немного сомнительна, и в других местах определенно существует потенциальная ошибка в отношении потоков.

+0

Но если это так, то как это возможно, работает на Wi-Fi, но не на 3G с точно таким же кодом? – Emilio

+0

Отличный вопрос! Ответ можно найти в трассировке пакетов, которая обнюхивает пакеты как Man In The Middle. Но сначала я бы проверил, связано ли соединение метода делегирования: needNewBodyStream: был вызван (возможно, как результат проверки подлинности), и если HTTPBodyStream запроса будет сбрасываться сетевой библиотекой. – CouchDeveloper

+0

Вы также можете проверить, будет ли запрос работать, если вы настроите запрос с помощью NSData (через свойство HTTPBody) вместо потока. Поскольку NSData может быть «перемотано» соединением внутри, нет проблем, когда вызов проверки подлинности вызвал повторный запрос. Обратите внимание, что все это может произойти прозрачно, поэтому вы должны проверить с помощью отладчика и трассировки пакетов. – CouchDeveloper

 Смежные вопросы

  • Нет связанных вопросов^_^