Как получить размер файла из заголовков http


Я хочу получить размер http:/.../ файл перед его загрузкой. Файл может быть веб-страницей, изображением или мультимедийным файлом. Можно ли это сделать с помощью заголовков HTTP? Как я могу скачать просто в заголовке файла по HTTP?

4 59

4 ответа:

да, предполагая, что HTTP-сервер, с которым вы разговариваете, поддерживает/разрешает это:

System.Net.WebRequest req = System.Net.HttpWebRequest.Create("http://stackoverflow.com/robots.txt");
req.Method = "HEAD";
using (System.Net.WebResponse resp = req.GetResponse())
{
    int ContentLength;
    if(int.TryParse(resp.Headers.Get("Content-Length"), out ContentLength))
    { 
        //Do something useful with ContentLength here 
    }
}

Если использование метода 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($"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);
            }
        }
    }
}