Domanda

Voglio ottenere le dimensioni di un file http: /.../ prima di scaricarlo. Il file può essere una pagina Web, un'immagine o un file multimediale. Questo può essere fatto con le intestazioni HTTP? Come faccio a scaricare solo l'intestazione HTTP del file?

È stato utile?

Soluzione

Sì, supponendo che il server HTTP con cui stai parlando lo supporti / lo consenta:

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

Se l'uso del metodo HEAD non è consentito o l'intestazione Content-Length non è presente nella risposta del server, l'unico modo per determinare la dimensione del contenuto sul server è scaricarlo. Poiché ciò non è particolarmente affidabile, la maggior parte dei server includerà queste informazioni.

Altri suggerimenti

  

È possibile farlo con le intestazioni HTTP?

Sì, questa è la strada da percorrere. Se le informazioni sono fornite, sono nell'intestazione come Content-Length . Si noti, tuttavia, che questo non è necessariamente il caso.

Il download solo dell'intestazione può essere eseguito utilizzando una richiesta HEAD anziché GET . Forse il seguente codice aiuta:

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

Nota la proprietà per la lunghezza del contenuto sull'oggetto HttpWebResponse - & nbsp; non è necessario analizzare manualmente l'intestazione Content-Length .

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

Nota che non tutti i server accettano richieste HTTP HEAD . Un approccio alternativo per ottenere la dimensione del file è di effettuare una chiamata HTTP GET al server richiedendo solo una parte del file per mantenere piccola la risposta e recuperare la dimensione del file dai metadati restituiti come parte dell'intestazione del contenuto della risposta.

Lo standard System.Net.Http.HttpClient può essere usato per fare questo. Il contenuto parziale viene richiesto impostando un intervallo di byte nell'intestazione del messaggio di richiesta come:

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

Il server risponde con un messaggio contenente l'intervallo richiesto e l'intera dimensione del file. Queste informazioni vengono restituite nell'intestazione del contenuto della risposta ( response.Content.Header ) con la chiave "Content-Range".

Ecco un esempio dell'intervallo di contenuti nell'intestazione del contenuto del messaggio di risposta:

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

In questo esempio il valore dell'intestazione implica che la risposta contiene byte da 0 a 15 (vale a dire, 16 byte in totale) e il file è 2.328.372 byte nella sua interezza.

Ecco un'implementazione di esempio di questo metodo:

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);
            }
        }
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top