2017-06-06 1 views
1

Sous UWP, la classe à faible niveau HttpWebRequest et son acabit ont été été désapprouvée et the official recommendation est d'utiliser System.Net.Http.HttpClientEmpêcher le téléchargement de la ressource distante entière avec HttpClient?

Cependant, il semble y avoir soit un oubli flagrant ou un bug dans la mise en œuvre HttpClient: l'API ne semble pas fournir un moyen de faire une demande à un URI distant qui ne télécharge pas automatiquement la ressource distante entière (dans le cas d'une demande GET) pour permettre une évaluation paresseuse du flux de réponse.

The documentation for the HttpClient.GetAsync() method dit:

Cette opération ne bloque pas. L'objet de tâche retourné se terminera après que toute la réponse (y compris le contenu) a été lue.

Qui indique d'emblée que la ressource distante entière sera téléchargée avant que la demande ne soit considérée comme terminée. Il y a un paramètre HttpCompletionOption qui permettrait théoriquement de travailler autour de ce si HttpCompletionOption.ResponseHeadersRead est spécifié, comme cela est documenté comme suit:

L'opération devrait compléter dès qu'une réponse est disponible et en-têtes sont lus. Le contenu n'est pas encore lu.

Cependant, quelle que soit HttpCompletionOption est spécifié, dans tous les cas, HttpClient.GetAsync() semble affecter les ContentLength complets octets de la réponse (en mémoire! À la fois! Sans contrôle de limite!) Dans le processus. Naturellement, c'est un peu fou et un vrai problème.

Dans mon cas particulier, je veux juste lire les premières kb d'une ressource distante de plusieurs gigaoctets à partir d'un serveur qui ne prend pas en charge les en-têtes de plage http. C'est normalement une opération «sans sueur»: il suffit de créer une requête Web, de lire le flux de réponse jusqu'à ce que vous soyez satisfait, puis de fermer la réponse et d'être à votre guise.

Cela ne semble pas être une option avec l'API HttpClient par défaut. Existe-t-il une solution de contournement simple qui n'implique pas l'élaboration de mes propres requêtes HTTP à l'aide de sockets raw?

Répondre

1

dans tous les cas, HttpClient.GetAsync() semble affecter les octets complets de ContentLength de la réponse (en mémoire! À la fois! Sans contrôle de limite!)

Ce n'est pas vrai pour l'option HttpCompletionOption.ResponseHeadersRead. Comme pour l'ancienne classe HttpWebRequest, vous pouvez ouvrir le flux de réponse et lire quelques octets, puis ignorer la réponse. Voici an example.

Voici mon expérience: (j'utilise Windows.Web.Http.HttpClient à la place, mais System.Net.Http.HttpClient fournit des API similaires)

private HttpClient httpClient = new HttpClient(); 
private CancellationTokenSource cts = new CancellationTokenSource(); 


private async void MainPage_Loaded(object sender, RoutedEventArgs e) 
{ 
    Uri resourceAddress = new Uri("http://somewhere/gigabyte.zip"); 

    try 
    { 
     HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Get, resourceAddress); 

     // Do not buffer the response. 
     HttpResponseMessage response = await httpClient.SendRequestAsync(
      request, 
      HttpCompletionOption.ResponseHeadersRead).AsTask(cts.Token); 

     using (Stream responseStream = (await response.Content.ReadAsInputStreamAsync()).AsStreamForRead()) 
     { 
      int read = 0; 
      byte[] responseBytes = new byte[1000]; 
      do 
      { 
       read = await responseStream.ReadAsync(responseBytes, 0, responseBytes.Length); 
       break; 
      } while (read != 0); 
     }     
    } 
    catch (TaskCanceledException) 
    {     
    } 
    catch (Exception ex) 
    { 
    } 
    finally 
    { 
    } 
} 
+0

Il semble que mon cas de test a été foireuse et n'a pas simuler de manière fiable les valeurs de 'HttpCompletionOptions'. –