Протокол HTTP длина содержимого - PullRequest
4 голосов
/ 05 апреля 2009

Я работаю над простым приложением для загрузки. При отправке запроса на следующий файл и Firefox, и мое приложение не получают поле content-length. Но если я сделаю запрос, используя сервер wget, отправлю поле content-length. Я изменил строку пользовательского агента wgets для проверки, и она все еще получила поле длины контента.

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

запрос wget

---request begin---
GET /dc-13/video/2005_Defcon_V2-P_Zimmerman-Unveiling_My_Next_Big_Project.mp4 HTTP/1.0
User-Agent: test
Accept: */*
Host: media.defcon.org
Connection: Keep-Alive

---request end---
HTTP request sent, awaiting response... 
---response begin---
HTTP/1.0 200 OK
Server: lighttpd
Date: Sun, 05 Apr 2009 04:40:08 GMT
Last-Modified: Tue, 23 May 2006 22:18:19 GMT
Content-Type: video/mp4
Content-Length: 104223909
Connection: keep-alive

запрос firefox

GET /dc-13/video/2005_Defcon_V2-P_Zimmerman-Unveiling_My_Next_Big_Project.mp4 HTTP/1.1
Host: media.defcon.org
User-Agent: Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.4; en-US; rv:1.9.0.8) Gecko/2009032608 Firefox/3.0.8
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive
Referer: http://www.defcon.org/html/links/defcon-media-archives.html
Pragma: no-cache
Cache-Control: no-cache

HTTP/1.x 200 OK
Server: lighttpd
Date: Sun, 05 Apr 2009 05:20:12 GMT
Last-Modified: Tue, 23 May 2006 22:18:19 GMT
Content-Type: video/mp4
Transfer-Encoding: chunked

Обновление:

Есть ли заголовок, который я могу отправить, который скажет Lighthttpd не использовать чанкованное кодирование. Моя оригинальная проблема заключается в том, что я использую urlConnection для получения файла в моем java-приложении, которое автоматически отправляет запрос HTTP 1.1.

Я хотел бы знать размер файла, чтобы я мог обновить свой процент.

Ответы [ 3 ]

13 голосов
/ 05 апреля 2009

GET /dc-13/video/2005_Defcon_V2-P_Zimmerman-Unveiling_My_Next_Big_Project.mp4 HTTP / 1.1

Firefox выполняет HTTP-запрос GET 1.1. Lighthttpd понимает, что клиент будет поддерживать кодирование chunked-Transfer, и возвращает содержимое в виде фрагментов, причем каждый блок сообщает свою собственную длину.

GET /dc-13/video/2005_Defcon_V2-P_Zimmerman-Unveiling_My_Next_Big_Project.mp4 HTTP / 1,0

Wget, с другой стороны, выполняет HTTP-запрос GET 1.0. Lighthttpd, понимая, что клиент не поддерживает HTTP 1.1 (и, следовательно, кодирует по частям), возвращает содержимое в виде одного фрагмента, длина которого указана в заголовке ответа.

4 голосов
/ 05 апреля 2009

Похоже, это из-за кодировки передачи chunked :

Transfer-Encoding: chunked

Это отправит видео по частям, каждый со своим размером. Это определено в HTTP 1.1, который используется Firefox, в то время как wget использует HTTP 1.0, который не поддерживает кодирование передачи по частям, поэтому сервер должен отправить весь файл сразу.

1 голос
/ 17 декабря 2013

У меня была такая же проблема, и я нашел решение независимо от того, какая версия HTTP:

  1. Сначала используйте HEAD запрос к серверу, который правильно отвечает только заголовком HTTP и без содержимого. Этот заголовок правильно включает требуемый размер Content-Length: байт для загружаемого файла.
  2. Выполните запрос GET для загрузки файла (в заголовке ответа GET не указана длина содержимого).

Пример языка Objective C:

NSString *zipURL = @"http://1.bp.blogspot.com/_6-cw84gcURw/TRNb3PDWneI/AAAAAAAAAYM/YFCZP1foTiM/s1600/paragliding1.jpg";

NSURL *url = [NSURL URLWithString:zipURL];

// Configure the HTTP request for HEAD header fetch
NSMutableURLRequest *urlRequest = [NSMutableURLRequest requestWithURL:url];
urlRequest.HTTPMethod = @"HEAD";  // Default is "GET"

// Define response class
__autoreleasing NSHTTPURLResponse *response;

// Send HEAD request to server
NSData *contentsData = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:&response error:nil];

// Header response field
NSDictionary *headerDeserialized = response.allHeaderFields;

// The contents length
int contents_length = [(NSString*)headerDeserialized[@"Content-Length"] intValue];

//printf("HEAD Response header: %s\n",headerDeserialized.description.UTF8String);
printf("HEAD:\ncontentsData.length: %d\n",contentsData.length);
printf("contents_length = %d\n\n",contents_length);

urlRequest.HTTPMethod = @"GET";

// Send "GET" to download file
contentsData = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:&response error:nil];

// Header response field
headerDeserialized = response.allHeaderFields;

// The contents length
contents_length = [(NSString*)headerDeserialized[@"Content-Length"] intValue];

printf("GET Response header: %s\n",headerDeserialized.description.UTF8String);
printf("GET:\ncontentsData.length: %d\n",contentsData.length);
printf("contents_length = %d\n",contents_length);

return;

И вывод:

HEAD:
contentsData.length: 0
contents_length = 146216

GET:
contentsData.length: 146216
contents_length = 146216

(Примечание. В этом примере URL-адрес правильно предоставляет заголовок Content-Length из ответа GET, но показывает идею, если это не удалось)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...