2017-06-06 237 views
1

在UWP,低級HttpWebRequest類及其之流已被棄用,並且the official recommendation是使用System.Net.Http.HttpClient防止下載?

然而,似乎無論是刺目的監督,或在該HttpClient實現中的錯誤:在API似乎沒有提供一種方法,使向遠程URI的請求,不自動下載整個遠程資源(在GET請求的情況下),以允許響應流的延遲計算。

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

此操作不會阻止。在讀取完整個響應(包括內容)之後,返回的任務對象將完成。

哪一種狀態顯示整個遠程資源將在請求被認爲完成之前下載。有一個HttpCompletionOption參數,理論上將允許這一點,如果HttpCompletionOption.ResponseHeadersRead工作圍繞指定,作爲被記錄如下:

操作應儘快完成的響應是可用的和頭被讀取。內容尚未讀取。

然而,無論哪個被指定HttpCompletionOption,在所有情況下,HttpClient.GetAsync()似乎在該過程分配完整ContentLength字節響應的(在存儲器!一次全部!無任何限制檢查!)。自然,這是有點瘋狂和真正的問題。

在我的特殊情況下,我只想從不支持http範圍標頭的服務器讀取幾千兆字節的遠程資源的前幾個kb。這通常是一個「無汗」操作:只要創建Web請求,從響應流中讀取直到您滿意爲止,然後關閉響應,並在你快樂的方式。

似乎並非是使用默認HttpClient API的選項。有一個簡單的解決辦法,不涉及使用手工製作原始套接字我自己的HTTP請求?

回答

1
在所有情況下

,HttpClient.GetAsync()似乎分配響應的完整的ContentLength字節(在內存!一下子!沒有任何限制檢查!)

這是不正確的HttpCompletionOption.ResponseHeadersRead選項。

就像使用舊的甜蜜HttpWebRequest類,你可以打開響應流和讀取幾個字節,然後丟棄該響應。這裏是an example

這裏是我的實驗:(我用Windows.Web.Http.HttpClient代替,但System.Net.Http.HttpClient提供了類似的API)

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

看來,我的測試用例是borked並沒有可靠地模擬'HttpCompletionOptions'值。 –