如何从HTTP标头获取文件大小


Answers:


95

是的,假设您正在与之通信的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标头,则确定服务器上内容大小的唯一方法是下载内容。由于这不是特别可靠,因此大多数服务器将包含此信息。


12
如果使用using它,则会自动将其丢弃。msdn.microsoft.com/zh-CN/library/yh598w02(v=vs.110).aspx
justderb

3
另一个注意事项是,如果仅对大型文件使用此int功能还不够,那么您将需要使用long ContentLength;long.TryParse(xxx)支持2.14GB以上的返回值。
普雷斯顿

是否启用HTTP压缩功能会抛出实际文件大小?
贾斯汀

我使用这种方法来知道此链接的大小:http://ipv4.download.thinkbroadband.com/200MB.zip但是出现错误403!为什么?
Behzad

28

可以使用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的文件的长度吗?
亚当·诺夫辛格

1
@Adam否。文档说:“ ContentLength属性包含响应返回的Content-Length标头的值。”
Konrad Rudolph

确保调用resp.Close(),否则一次执行多个请求时会遇到超时错误(我的第三个请求在foreach循环中超时,已通过关闭每个响应来解决)
Eric Smith,

3
@Eric实际上,您应该Using在此处使用一个块,或者实现一次性模式来显式管理资源的生存期。Close除非确保始终发生错误,否则手动调用是不够的。
Konrad Rudolph

@KonradRudolph你是完全正确的。在测试此函数时,调用Close()修复了我的错误,但是using块是正确的方法。德普
埃里克·史密斯

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个字节),并且文件整体为2328372字节。

这是此方法的示例实现:

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);
            }
        }
    }
}

不错的解决方案,但并非每个服务器都允许内容范围请求。
Phani Rithvij,

1
WebClient webClient = new WebClient();
webClient.OpenRead("http://stackoverflow.com/robots.txt");
long totalSizeBytes= Convert.ToInt64(webClient.ResponseHeaders["Content-Length"]);
Console.WriteLine((totalSizeBytes));

2
这是一个很好的解决方案,尤其是如果您已经在使用WebClient下载文件,并且只想添加首先检查文件长度的话。
ScottFoster1000 '18 -10-22
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.