Comment obtenir la taille du fichier à partir des en-têtes http
-
02-07-2019 - |
Question
Je souhaite obtenir la taille d’un fichier http: /.../ avant de le télécharger. Le fichier peut être une page Web, une image ou un fichier multimédia. Cela peut-il être fait avec des en-têtes HTTP? Comment télécharger uniquement l'en-tête HTTP du fichier?
La solution
Oui, en supposant que le serveur HTTP auquel vous parlez prend en charge / autorise ceci:
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 l'utilisation de la méthode HEAD n'est pas autorisée ou si l'en-tête Content-Length n'est pas présent dans la réponse du serveur, le seul moyen de déterminer la taille du contenu du serveur consiste à le télécharger. Comme cela n’est pas particulièrement fiable, la plupart des serveurs incluront ces informations.
Autres conseils
Cela peut-il être fait avec des en-têtes HTTP?
Oui, c'est la voie à suivre. Si les informations sont fournies, elles figurent dans l'en-tête sous la forme Content-Length
. Notez cependant que ce n'est pas nécessairement le cas.
Le téléchargement de l'en-tête uniquement peut être effectué à l'aide d'une requête HEAD
au lieu de GET
. Peut-être que le code suivant peut aider:
HttpWebRequest req = (HttpWebRequest)WebRequest.Create("http://example.com/");
req.Method = "HEAD";
long len;
using(HttpWebResponse resp = (HttpWebResponse)(req.GetResponse()))
{
len = resp.ContentLength;
}
Notez la propriété de la longueur du contenu sur l'objet HttpWebResponse
& # 8211; & nbsp; inutile d'analyser manuellement l'en-tête Content-Length
.
WebClient webClient = new WebClient();
webClient.OpenRead("http://stackoverflow.com/robots.txt");
long totalSizeBytes= Convert.ToInt64(webClient.ResponseHeaders["Content-Length"]);
Console.WriteLine((totalSizeBytes));
Notez que tous les serveurs n'acceptent pas les requêtes HTTP HEAD
. Une autre solution pour obtenir la taille du fichier consiste à appeler le serveur HTTP GET
, lui demandant de ne conserver qu’une partie du fichier afin de conserver une réponse réduite et d’extraire la taille du fichier à partir des métadonnées renvoyées. de l'en-tête de contenu de la réponse.
Le standard System.Net.Http.HttpClient
peut être utilisé à cette fin. Le contenu partiel est demandé en définissant une plage d'octets sur l'en-tête du message de requête comme suit:
request.Headers.Range = new RangeHeaderValue(startByte, endByte)
Le serveur répond avec un message contenant la plage demandée ainsi que la taille totale du fichier. Ces informations sont renvoyées dans l'en-tête du contenu de la réponse ( response.Content.Header
) avec la clé "Content-Range".
Voici un exemple de la plage de contenu dans l'en-tête de contenu du message de réponse:
{
"Key": "Content-Range",
"Value": [
"bytes 0-15/2328372"
]
}
Dans cet exemple, la valeur de l'en-tête implique que la réponse contient les octets 0 à 15 (soit un total de 16 octets) et que le fichier contient 2 328 372 octets.
Voici un exemple d'implémentation de cette méthode:
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);
}
}
}
}