5

進度條我想運行在WPF的進度條異步上傳(最好使用PCL在Xamarin和SL代碼重用了。)爲HttpClient的上傳

我一直在嘗試使用System.Net。 HttpClient的。 不幸的是,PutAsync不提供任何進度通知。 (我知道它適用於Windows.Web.Http.HttpClient,但這不適用於WPF,也不適用於PCL)。

對於下載,它很容易實現你自己的進度條,如描述here。您只需傳遞ResponseHeadersRead選項,該選項會在返回頭文件後立即使用該流,然後按塊大塊讀取它,隨着您的進度增加進度條。但是對於上傳,這種技術不起作用 - 您需要一次性將所有上傳數據傳遞給PutAsync,因此無法增加計數器。

我也想知道如何使用HttpClient.SendAsync。我希望我可以像對待異步HttpWebRequest一樣對待它(在您寫入HttpWebRequest.GetRequestStream時,您可以像計算here所述那樣增加計數器)。但不幸的是HttpClient.SendAsync不會給你可寫的流,所以這是行不通的。

那麼HttpClient支持上傳的非阻塞用戶界面和進度條?這似乎是一個溫和的需求。還是有我應該使用的另一個班級?非常感謝。

回答

4

假設HttpClient(和底層網絡堆棧)沒有緩衝,你應該可以通過覆蓋HttpContent.SerializeToStreamAsync來做到這一點。你可以做類似如下:

 const int chunkSize = 4096; 
     readonly byte[] bytes; 
     readonly Action<double> progress; 

     protected override async Task SerializeToStreamAsync(System.IO.Stream stream, System.Net.TransportContext context) 
     { 
      for (int i = 0; i < this.bytes.Length; i += chunkSize) 
      { 
       await stream.WriteAsync(this.bytes, i, Math.Min(chunkSize, this.bytes.Length - i)); 
       this.progress(100.0 * i/this.bytes.Length); 
      } 
     } 

爲了避免HttpClient的被緩衝,你要麼需要提供內容長度(如:實施HttpContent.TryComputeLength,或設置頭)或啓用HttpRequestHeaders.TransferEncodingChunked。這是必要的,否則HttpClient無法確定內容長度標題,所以它首先將整個內容讀入內存。

在電話8上,您還需要禁用AllowAutoRedirect,因爲WP8在處理重定向帖子的方式中存在一個錯誤(解決方法是首先發出HEAD,獲取重定向的URL,然後使用AllowAutoRedirect將該帖子發送到最終的URL = false)。

+0

是的,這似乎工作。 (到目前爲止,我只在WPF,.net 4.5.1中測試過它)。非常感謝! – thund