Http协议内容长度

时间:2009-04-05 04:53:13

标签: http http-headers

我正在开发一个简单的下载应用程序。在请求以下文件时,firefox和我的应用程序都没有获取content-length字段。但是如果我使用wget服务器发出请求会发送内容长度字段。我确实更改了wgets用户代理字符串以进行测试,它仍然有内容长度字段。

为什么会发生这种情况?

wget request

---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来抓取我自己发送HTTP 1.1请求的java应用程序中的文件。

我想知道文件的大小,以便我可以更新我的百分比。

3 个答案:

答案 0 :(得分:13)

  

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

Firefox正在执行HTTP 1.1 GET请求。 Lighthttpd理解客户端将支持分块传输编码并以块的形式返回内容,每个块报告自己的长度。

  

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

另一方面,Wget执行HTTP 1.0 GET请求。 Lighthttpd,了解客户端不支持HTTP 1.1(以及因此分块传输编码),在一个块中返回内容,并在响应头中报告长度。

答案 1 :(得分:4)

看起来是因为chunked transfer encoding

Transfer-Encoding: chunked

这将以视频形式发送视频,每个视频都有自己的大小。这是在HTTP 1.1中定义的,这是Firefox正在使用的,而wget正在使用HTTP 1.0,它不支持分块传输编码,因此服务器必须立即发送整个文件。

答案 2 :(得分:1)

我遇到了同样的问题,无论哪个HTTP版本都找到了解决方案:

  1. 首先向服务器使用HEAD请求,该请求仅使用HTTP标头正确响应而没有内容。此标头正确包含要下载的文件所需的Content-Length:字节大小。
  2. 继续GET下载文件的请求(GET响应中的标题无法包含Content-length)。
  3. 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
    

    (注意:此示例网址正确地提供了来自GET响应的标题Content-Length,但显示了它是否失败的想法)