【问题标题】:How to get the file size from http headers如何从 http 标头获取文件大小
【发布时间】:2010-09-12 11:29:18
【问题描述】:

我想在下载之前获取 http:/.../file 的大小。该文件可以是网页、图像或媒体文件。这可以用 HTTP 标头完成吗?如何只下载文件 HTTP 标头?

【问题讨论】:

    标签: c# http download http-headers


    【解决方案1】:

    是的,假设您正在与之通信的 HTTP 服务器支持/允许这样做:

    public long GetFileSize(string url)
    {
        long result = -1;
    
        System.Net.WebRequest req = System.Net.WebRequest.Create(url);
        req.Method = "HEAD";
        using (System.Net.WebResponse resp = req.GetResponse())
        {
            if (long.TryParse(resp.Headers.Get("Content-Length"), out long ContentLength))
            {
                result = ContentLength;
            }
        }
    
        return result;
    }
    

    如果不允许使用 HEAD 方法,或者服务器回复中不存在 Content-Length 标头,则确定服务器上内容大小的唯一方法是下载它。由于这不是特别可靠,因此大多数服务器都会包含此信息。

    【讨论】:

    • 如果您使用using,它会自动处理它。 msdn.microsoft.com/en-us/library/yh598w02(v=vs.110).aspx
    • 另外注意,如果你将这个用于超大文件int 是不够的,你需要使用long ContentLength;long.TryParse(xxx) 来支持超过 2.14GB 大小的返回值.
    • 启用 http 压缩不会影响实际文件大小吗?
    • 我用这个方法来知道这个链接的大小:http://ipv4.download.thinkbroadband.com/200MB.zip但是得到一个错误403!为什么?
    【解决方案2】:

    这可以通过 HTTP 标头完成吗?

    是的,这是要走的路。 如果提供了信息,它在标题中为Content-Length。但请注意,情况不一定如此。

    可以使用HEAD 请求而不是GET 来仅下载标头。也许下面的代码有帮助:

    HttpWebRequest req = (HttpWebRequest)WebRequest.Create("http://example.com/");
    req.Method = "HEAD";
    long len;
    using(HttpWebResponse resp = (HttpWebResponse)(req.GetResponse()))
    {
        len = resp.ContentLength;
    }
    

    注意 HttpWebResponse 对象的内容长度属性 - 无需手动解析 Content-Length 标头。

    【讨论】:

    • 上面的 resp.ContentLength 不会给你 HEAD 响应的长度,而不是你有兴趣获取 sizeof 的文件的长度吗?
    • @Adam 否。文档说:“ContentLength 属性包含随响应返回的 Content-Length 标头的值。”
    • 确保调用 resp.Close() 否则在一次发出多个请求时可能会遇到超时错误(我的第三个请求在 foreach 循环中超时,通过关闭每个响应来解决)
    • @Eric 实际上你应该在这里使用Using 块,或者实现一次性模式来显式地管理资源的生命周期。手动调用 Close 是不够的,除非您确保它总是发生,即使发生错误。
    • @KonradRudolph 你说得对。在我测试这个时调用 Close() 修复了我的错误,但是使用块是正确的方法。德普。
    【解决方案3】:

    请注意,并非每个服务器都接受HTTP HEAD 请求。获取文件大小的另一种方法是对服务器进行HTTP GET 调用,仅请求文件的一部分以保持响应较小,并从作为响应内容标头的一部分返回的元数据中检索文件大小。

    标准System.Net.Http.HttpClient 可用于完成此操作。通过在请求消息头上设置字节范围来请求部分内容:

        request.Headers.Range = new RangeHeaderValue(startByte, endByte)
    

    服务器以包含请求范围以及整个文件大小的消息进行响应。此信息在响应内容标头 (response.Content.Header) 中返回,键为“Content-Range”。

    这是响应消息内容标头中内容范围的示例:

        {
           "Key": "Content-Range",
           "Value": [
             "bytes 0-15/2328372"
           ]
        }
    

    在此示例中,标头值意味着响应包含字节 0 到 15(即总共 16 个字节),并且文件总共有 2,328,372 个字节。

    这是此方法的示例实现:

    public static class HttpClientExtensions
    {
        public static async Task<long> GetContentSizeAsync(this System.Net.Http.HttpClient client, string url)
        {
            using (var request = new System.Net.Http.HttpRequestMessage(System.Net.Http.HttpMethod.Get, url))
            {
                // In order to keep the response as small as possible, set the requested byte range to [0,0] (i.e., only the first byte)
                request.Headers.Range = new System.Net.Http.Headers.RangeHeaderValue(from: 0, to: 0);
    
                using (var response = await client.SendAsync(request))
                {
                    response.EnsureSuccessStatusCode();
    
                    if (response.StatusCode != System.Net.HttpStatusCode.PartialContent) 
                        throw new System.Net.WebException($"expected partial content response ({System.Net.HttpStatusCode.PartialContent}), instead received: {response.StatusCode}");
    
                    var contentRange = response.Content.Headers.GetValues(@"Content-Range").Single();
                    var lengthString = System.Text.RegularExpressions.Regex.Match(contentRange, @"(?<=^bytes\s[0-9]+\-[0-9]+/)[0-9]+$").Value;
                    return long.Parse(lengthString);
                }
            }
        }
    }
    

    【讨论】:

    • 不错的解决方案,但不是每个服务器都允许内容范围请求。
    【解决方案4】:
    WebClient webClient = new WebClient();
    webClient.OpenRead("http://stackoverflow.com/robots.txt");
    long totalSizeBytes= Convert.ToInt64(webClient.ResponseHeaders["Content-Length"]);
    Console.WriteLine((totalSizeBytes));
    

    【讨论】:

    • 这是一个很好的解决方案,特别是如果您已经在使用 WebClient 下载文件并且只想添加检查文件长度。
    猜你喜欢
    • 2017-08-26
    • 2014-07-25
    • 1970-01-01
    • 2012-10-25
    • 2015-04-11
    • 2014-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多