我希望在下载之前获取http:/.../文件的大小。该文件可以是网页,图像或媒体文件。可以使用HTTP标头完成吗?如何仅下载文件HTTP标头?

有帮助吗?

解决方案

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

其他提示

  

可以使用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 标题。

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

请注意,并非每个服务器都接受 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(<*>quot;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]+<*>quot;).Value;
                return long.Parse(lengthString);
            }
        }
    }
}
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top