Pregunta

Quiero obtener el tamaño de un archivo http:/.../ antes de descargarlo.El archivo puede ser una página web, una imagen o un archivo multimedia.¿Se puede hacer esto con encabezados HTTP?¿Cómo descargo solo el encabezado HTTP del archivo?

¿Fue útil?

Solución

Sí, suponiendo que el servidor HTTP con el que estás hablando admita/permita esto:

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

Si no se permite el uso del método HEAD, o el encabezado Content-Length no está presente en la respuesta del servidor, la única forma de determinar el tamaño del contenido en el servidor es descargarlo.Dado que esto no es particularmente confiable, la mayoría de los servidores incluirán esta información.

Otros consejos

¿Se puede hacer esto con encabezados HTTP?

Sí, este es el camino a seguir. Si se proporciona la información, está en el encabezado como Content-Length.Tenga en cuenta, sin embargo, que este no es necesariamente el caso.

La descarga sólo del encabezado se puede realizar mediante un HEAD solicitar en lugar de GET.Quizás el siguiente código ayude:

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

Observe la propiedad para la longitud del contenido en el HttpWebResponse objeto: no es necesario analizar el Content-Length encabezado manualmente.

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

Tenga en cuenta que no todos los servidores aceptan HTTP HEAD peticiones.Un método alternativo para obtener el tamaño del archivo es hacer un HTTP GET llama al servidor solicitando solo una parte del archivo para mantener la respuesta pequeña y recuperar el tamaño del archivo de los metadatos que se devuelven como parte del encabezado del contenido de la respuesta.

El estandar System.Net.Http.HttpClient puede usarse para lograr esto.El contenido parcial se solicita estableciendo un rango de bytes en el encabezado del mensaje de solicitud como:

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

El servidor responde con un mensaje que contiene el rango solicitado así como el tamaño completo del archivo.Esta información se devuelve en el encabezado del contenido de la respuesta (response.Content.Header) con la clave "Rango de contenidos".

A continuación se muestra un ejemplo del rango de contenido en el encabezado del contenido del mensaje de respuesta:

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

En este ejemplo, el valor del encabezado implica que la respuesta contiene del 0 al 15 bytes (es decir, 16 bytes en total) y que el archivo tiene 2.328.372 bytes en su totalidad.

Aquí hay una implementación de muestra de este método:

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);
            }
        }
    }
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top