【问题标题】:Http protocol content-lengthHttp协议内容长度
【发布时间】:2010-10-17 15:07:29
【问题描述】:

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

任何想法为什么会发生这种情况?

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

火狐请求

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 请求。

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

【问题讨论】:

  • 如果您支持 HTTP 1.1,您必须支持分块编码。

标签: http http-headers


【解决方案1】:

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

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

获取 /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(因此分块传输编码),将内容以单个块的形式返回,长度在响应标头中报告。

【讨论】:

  • 是否有我可以发送的标头告诉 Lighthttpd 不要使用分块编码。我最初的问题是我正在使用 urlConnection 来获取我的 java 应用程序中的文件,该文件会自动发送 HTTP 1.1 请求。我想知道文件的大小,以便更新我的百分比。谢谢。
  • 您正在寻找的不是请求标头,而是一种更改客户端使用的协议版本的方法。您需要客户端发出 1.0 请求。您使用的是什么 HTTP 客户端库?
【解决方案2】:

看起来是因为chunked transfer encoding

Transfer-Encoding: chunked

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

【讨论】:

    【解决方案3】:

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

    1. 首先向服务器发出HEAD 请求,该请求正确响应,仅包含HTTP 标头而没有内容。此标头正确包含要下载的文件所需的 Content-Length: 字节大小。
    2. 继续 GET 请求以下载文件(GET 响应的标头未能包含 Content-length)。

    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 确实从 GET 响应中正确提供了标头 Content-Length,但如果未能提供,则会显示该想法)

    【讨论】:

    • HEAD请求的响应不包含实体,因此不需要包含Content-Length头。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-18
    • 1970-01-01
    • 2015-04-30
    • 2013-01-23
    • 2012-04-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多