Я хочу получить размер файла http: /.../ перед его загрузкой. Файл может быть веб-страницей, изображением или медиафайлом. Можно ли это сделать с помощью заголовков HTTP? Как загрузить только HTTP-заголовок файла?
Как получить размер файла из заголовков http
Ответы (4)
Да, при условии, что 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
- person justderb; 17.04.2013
int
недостаточно, вам нужно использовать long ContentLength;
и long.TryParse(xxx)
для поддержки возвращаемого значения размером более 2,14 ГБ.
- person Preston; 16.10.2015
http://ipv4.download.thinkbroadband.com/200MB.zip
, но получаю ошибку 403! Зачем?
- person Behzad; 21.04.2020
Можно ли это сделать с помощью заголовков 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?
- person Adam Nofsinger; 19.04.2011
Using
или реализовать одноразовый шаблон для явного управления временем жизни ресурса. Вызов Close
вручную недостаточно, если вы не уверены, что это всегда происходит, даже в случае ошибки.
- person Konrad Rudolph; 26.03.2013
ContentLength
возвращает long
. Ничего страшного, но на всякий случай, если вы захотите это исправить.
- person gunr2171; 02.05.2013
Обратите внимание, что не каждый сервер принимает 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);
}
}
}
}