Класс Android URLConnection не может получить длину контента, используя подключение к Интернету 3G

У меня есть следующий фрагмент кода:

URL url = new URL("http://myserver.com/getFile.php");
URLConnection conexion = url.openConnection();
conexion.connect();
int lenghtOfFile = conexion.getContentLength();

Все работает нормально, пока я не работаю с WiFi-соединением. Если я попытаюсь запустить этот код, когда доступно только соединение GPRS/3G, conexion.getContentLength() вернет -1.

Есть идеи, почему?

РЕДАКТИРОВАТЬ: я проверил заголовки, используя getHeaderFields(). Они отличаются, если я использую сеть 3G. По сути, в этом случае Content-Length нет. Любая идея, почему сервер возвращает разные заголовки? Я не использую какой-либо специальный скрипт для предоставления файла, я получаю только файл, который находится в заданном месте.

Весь заголовок для случая WiFi:

{Accept-Ranges=[bytes], Connection=[Keep-Alive], Content-Length=[628254], Content-Type=[text/plain; charset=UTF-8], Date=[Вторник, 29 ноября 2011 г., 11:22:50 по Гринвичу], ETag=["7a0c7-9961e-4af3f38778500"], Keep-Alive=[timeout=15], Last-Modified=[ Пт, 14 октября 2011 г., 09:52:52 по Гринвичу], Server=[Apache/2.2.9 (Debian) PHP/5.2.6-1+lenny9 с Suhosin-Patch mod_python/3.3.1 Python/2.6.6 mod_ssl/2.2 .9 OpenSSL/0.9.8o mod_wsgi/3.3 mod_perl/2.0.4 Perl/v5.10.0]}

Вся шапка для случая при использовании 3G:

{Accept-Ranges=[bytes], Connection=[Keep-Alive], Content-Type=[text/plain; charset=UTF-8], Date=[Вторник, 29 ноября 2011 г., 11:20:33 по Гринвичу], ETag=["7a0c7-9961e-4af3f38778500"], Keep-Alive=[timeout=15], Last-Modified=[ Пт, 14 октября 2011 г., 09:52:52 по Гринвичу], Server=[Apache/2.2.9 (Debian) PHP/5.2.6-1+lenny9 с Suhosin-Patch mod_python/3.3.1 Python/2.6.6 mod_ssl/2.2 .9 OpenSSL/0.9.8o mod_wsgi/3.3 mod_perl/2.0.4 Perl/v5.10.0], Transfer-Encoding=[chunked], Warning=[214 warkaz-fe07 "Трансформация применена"]}


person kmalmur    schedule 29.11.2011    source источник
comment
Вы отключили Accept-Encoding:gzip с помощью HttpURLConnection? В моем случае я получил Transfer-Encoding: chunked, а Content-Length был отрицательным, для более подробной информации посмотрите мой ответ: stackoverflow.com/a/23490820/1294681   -  person VinceStyling    schedule 06.05.2014


Ответы (3)


Вы уверены, что сервер предоставляет длину контента, отправляя заголовок Content-Length в ответе?

Из заголовков видно, что у вашего провайдера есть какой-то прокси-сервер, который выполняет преобразование, удаляя длину содержимого в процессе. Заголовок предупреждения ясно указывает на это. Вы можете попробовать вернуть другой тип контента (теперь вы получаете текстовый/обычный), возможно, этот конкретный прокси его не коснется. Конечно, это не очень хорошее решение, у операторов есть много вещей, которые, возможно, придется каким-то образом «оптимизировать» в своей сети.

Вы также можете попробовать запрос HEAD, используя заголовок диапазона, чтобы получить приблизительный размер содержимого. В этом случае вы угадаете несколько диапазонов, например 100 тыс., 1000 тыс. и т. д., чтобы увидеть, считает ли сервер приемлемым диапазон. Вы можете использовать этот поддельный диапазон для своего прогресса. Опять же, это не очень хорошее решение, но если вам действительно нужен прогресс, стоит попробовать.

В конце концов, лучше просто показать прогресс как неизвестный, если длина неизвестна.

person botteaap    schedule 29.11.2011
comment
Я обновил вопрос. Вы правы, в случае, когда я использую сеть 3G, сервер не отправляет заголовок Content-Lenght - person kmalmur; 29.11.2011
comment
Я обновил свой ответ, учитывая, что в 3G есть прокси, который в вашем случае удаляет заголовок. - person botteaap; 04.12.2011

Поскольку вы используете

new URL("http://myserver.com/getFile.php");

Я предполагаю, что вы используете личный сервер, который вы настроили, и при использовании WiFi ваш телефон находится в вашей локальной сети и, таким образом, может видеть ваш сервер, но когда вы пытаетесь подключиться через GPR/3G, вы пытаетесь получить доступ к своему локальному сервер из интернета.

person Nermin Softic    schedule 29.11.2011
comment
myserver.com/getFile.php — это только пример, в моем приложении я использую работающий сервер, виден за пределами моей локальной сети. Во всяком случае, единственная проблема, которая у меня есть, это getConnectionLength, загрузка файла работает, но я не могу показать прогресс. - person kmalmur; 29.11.2011

Вероятно, это связано с ограничением вашего оператора. Старайтесь не использовать это значение. (например, читая inputStream до тех пор, пока вы не сможете его прочитать).

person njzk2    schedule 29.11.2011
comment
да, но если это так, я не могу показать прогресс при загрузке файла - person kmalmur; 29.11.2011
comment
это правда, но всегда есть случаи, когда вы не знаете общую длину, если сервер или оператор связи не позволяют вам ее получить. - person njzk2; 29.11.2011