Получить правильную длину содержимого удаленных файлов

Я пытаюсь получить длину содержимого удаленного файла, чтобы ограничить размер загрузки удаленных изображений следующим образом:

 WebResponse response = this.GetWebRequest().GetResponse();

 long contentLength = response.ContentLength;

 // WebResponse.ContentLength doesn't always know the value, 
 // it returns -1 in this case.
 if (contentLength == -1)
 {
     // Response headers may still have the Content-Length inside of it.
     string headerContentLength = response.Headers["Content-Length"];

     if (!String.IsNullOrWhiteSpace(headerContentLength))
     {
         contentLength = long.Parse(headerContentLength,
                                            CultureInfo.InvariantCulture);
     }
 }

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

Я прочитал аналогичные вопросы здесь и здесь это, кажется, указывает на то, что я мог бы каким-то образом использовать свойство Transfer-Encoding=chunked для определения длины, но я не нашел примера того, как это сделать.

Это возможно? Может ли кто-нибудь предоставить мне пример кода?


person James South    schedule 12.01.2012    source источник
comment
Это необязательно (хотя я предполагаю, что оно почти всегда будет там для изображений), поэтому нет, вы не можете определить это значение во всех случаях.   -  person BrokenGlass    schedule 12.01.2012
comment
@BrokenGlass Я бы так и подумал, но и отладка, и проверка с помощью firebug указывают на обратное. Изображение, на которое я смотрю, находится здесь images.mymovies.net/ images/film/cin/500x377/fid10122.jpg   -  person James South    schedule 12.01.2012
comment
@James Юг: Я вижу Content-Length: 33566 в ответ на этого конкретного URL: hurl.it/hurls/c79a3f4611819c370e53a30d07958ee1892862b9/   -  person Piskvor left the building    schedule 12.01.2012
comment
@Piskvor: Странно ... hurl.it, должно быть, загружает файл и сообщает о длине или использует что-то более умное, чем мой сервер разработки, поскольку я вообще не получаю это свойство.   -  person James South    schedule 12.01.2012
comment
@James South: Все мои клиенты (FF 9, Chrome 16, IE 6,7,8, Opera 11, wget 1.12), кажется, согласны с Hurl здесь (из разных мест в Интернете, не меньше) - я видя точно такие же заголовки. Вы уверены, что это не на вашей стороне?   -  person Piskvor left the building    schedule 12.01.2012
comment
@Piskvor: Я тупой? skydrive.live.com/   -  person James South    schedule 12.01.2012
comment
@James South: я никогда не говорил ничего подобного; однако между вами и исходным сервером может быть что-то (например, прокси-сервер), изменяющее ваш HTTP-трафик.   -  person Piskvor left the building    schedule 12.01.2012
comment
Хм... Я тоже не вижу Content-Length в Firebug, но я вижу, как он передается по сети, когда я перехватываю необработанный сетевой трафик с помощью Wireshark! Так что это может быть ошибка отображения Firebug; возможно, попробуйте посмотреть трафик в Fiddler2, это отличный прокси-сервер для отладки HTTP (для Windows). Надстройки Firefox, возможно, не получают полные заголовки (?); поскольку Fiddler является прокси-сервером, он точно показывает, что передается по сети.   -  person Piskvor left the building    schedule 12.01.2012
comment
@Piskvor: Cheers. Теперь я думаю, что может быть проще создать белый список сайта и разрешать удаленные файлы только оттуда.   -  person James South    schedule 12.01.2012


Ответы (1)


Нет, в общем случае это невозможно.

Единственный способ быть уверенным — загрузить весь ресурс и посмотреть, насколько он велик. В случае с динамически генерируемыми и/или потоковыми ресурсами может быть невозможно определить, какого размера будет ответ (например, прямой поток даже не обязательно имеет четко определенное начало или конец - он может просто продолжать отправлять поток как один огромный фрагментированный ответ).

Свойство chunked является обходным решением для неизвестного размера: перед фрагментами указывается размер следующего фрагмента; однако невозможно предсказать, сколько будет фрагментов и какого размера.

Кроме того: обратите внимание на Content-Length, существуют (даже в 2012 году!) реализации с ошибками, которые будут неверно сообщать об этом.

person Piskvor left the building    schedule 12.01.2012
comment
Таким образом, нет возможности открыть, загрузить до верхнего предела, а затем закрыть фрагментированное соединение после того, как вы его открыли? - person James South; 12.01.2012
comment
@James South: О, конечно - вы можете открыть, отправить запрос, а затем продолжать загрузку, пока сервер не сообщит вам, что больше нет фрагментов. Просто невозможно сказать, когда именно это произойдет, пока это не произойдет (в этот момент у вас есть полный ответ, и вы можете просто проверить его размер в байтах). - person Piskvor left the building; 12.01.2012
comment
Итак, что мне нужно сделать, это загружать каждый фрагмент за раз, проверяя длину следующего и добавляя соответствующие длины фрагментов, закрывая соединение, как только общая длина достигает моего верхнего предела размера фрагмента? - person James South; 12.01.2012
comment
@James South: таким образом вы можете получить неполный ответ (если ваш верхний предел слишком низок); лучшим подходом было бы закрыть соединение, когда вы получаете фрагмент нулевого размера (поскольку это маркер завершения передачи). Но да, установка ограничения может быть полезной, если у вас есть приблизительное представление о ожидаемом размере (например, 5 МБ для изображений должно быть достаточно в 2012 году). - person Piskvor left the building; 12.01.2012
comment
Круто ... Я бы примерно знал, каков будет мой верхний предел, так что есть идеи, как это закодировать? Я в тупике. - person James South; 12.01.2012
comment
@James South: Возможно, вы захотите просмотреть Интернет (кто-то, возможно, уже сделал это для вас), а затем, возможно, задать его как новый вопрос. (См. спецификацию RFC, на самом деле это довольно просто: w3. org/Protocols/rfc2616/rfc2616-sec3.html#sec3.6.1 ) - person Piskvor left the building; 12.01.2012