2016-04-05 114 views
0

我需要在應用程序內提供任意文件的下載進度。 我以爲我可以使用HttpClient.GetInputStreamAsync進度,但它不是很好。進度通知非常罕見。下面的代碼:Windows Store應用程序HttpClient進度

var httpClient = new HttpClient(); 
var path = new Uri(@"http://<path>"); 

using (var inputStream = (await httpClient.GetInputStreamAsync(path).AsTask(new MyProgress())).AsStreamForRead()) 
{ 
    var outputFile = await ApplicationData.Current.TemporaryFolder.CreateFileAsync("output.mov", CreationCollisionOption.ReplaceExisting); 

    using (var outputStream = (await outputFile.OpenAsync(FileAccessMode.ReadWrite)).AsStreamForWrite()) 
    { 
     await inputStream.CopyToAsync(outputStream); 

     await outputStream.FlushAsync(); 
    } 
} 

Debug.WriteLine("done"); 


private class MyProgress : IProgress<HttpProgress> 
{ 
    public void Report(HttpProgress value) 
    { 
     Debug.WriteLine("HTTP {0} progress {1}/{2}", value.Stage, value.BytesReceived, value.TotalBytesToReceive); 
    } 
} 

輸出:

HTTP ResolvingName progress 0/ 
HTTP ConnectingToServer progress 0/ 
HTTP SendingHeaders progress 0/ 
HTTP WaitingForResponse progress 0/ 
HTTP ReceivingHeaders progress 0/ 
HTTP ReceivingContent progress 0/109192147 
done 

所以在時間接收的總字節數是已知的一些點,但沒有文件下載過程中報告進度。

回答

0

由於HttpClient.GetInputStreamAsync不支持文件下載過程的進展,你可以使用HttpClientGetAsyncGetBufferAsync。下面的代碼更新代碼的使用HttpClient.GetAsync的其他方法。

var httpClient = new HttpClient(); 
    var path = new Uri("https://sec.ch9.ms/slides/developerGuideToWindows10/02-XAMLcontrols.pptx"); 
    HttpResponseMessage response = await httpClient.GetAsync(path).AsTask(new MyProgress()); 
    using (Stream responseStream = (await response.Content.ReadAsInputStreamAsync()).AsStreamForRead()) 
    { 
     var outputFile = await ApplicationData.Current.TemporaryFolder.CreateFileAsync("output.pptx", CreationCollisionOption.ReplaceExisting); 
     using (var outputStream = (await outputFile.OpenAsync(FileAccessMode.ReadWrite)).AsStreamForWrite()) 
     { 
      await responseStream.CopyToAsync(outputStream); 
      await outputStream.FlushAsync(); 
     } 
    } 
    Debug.WriteLine("done"); 

,輸出

enter image description here

+0

它做報告的進展,但同時也加載的所有內容到內存是我想避免什麼。對不起,遲到了,很忙。 – aguyngueran

0

我結束了與解決方案如下圖所示:

var httpClient = new HttpClient(); 

var path = new Uri(@"http://<path>"); 

var progressHelper = new ProgressHelper(); 

using (var inputStream = (await httpClient.GetInputStreamAsync(path).AsTask(progressHelper)).AsStreamForRead()) 
{ 
    var outputFile = await ApplicationData.Current.TemporaryFolder.CreateFileAsync("output.mov", CreationCollisionOption.ReplaceExisting); 

    using (var outputStream = (await outputFile.OpenAsync(FileAccessMode.ReadWrite)).AsStreamForWrite()) 
    { 
     var buffer = new byte[1024 * 1024]; 
     int read; 

     while ((read = await inputStream.ReadAsync(buffer, 0, buffer.Length)) > 0) 
     { 
      progressHelper.BytesReceived += (ulong)read; 

      await outputStream.WriteAsync(buffer, 0, read); 
     } 

     await outputStream.FlushAsync(); 
    } 
} 

Debug.WriteLine("done"); 


private class ProgressHelper : IProgress<HttpProgress> 
{ 
    private ulong _bytesReceived = 0; 
    private ulong? _totalBytesToReceive = null; 

    public void Report(HttpProgress value) 
    { 
     Debug.WriteLine("HTTP {0} progress {1}/{2}", value.Stage, value.BytesReceived, value.TotalBytesToReceive); 

     TotalBytesToReceive = value.TotalBytesToReceive;     
    } 

    public ulong? TotalBytesToReceive 
    { 
     get 
     { 
      return _totalBytesToReceive; 
     } 
     set 
     { 
      if (_totalBytesToReceive == value) 
       return; 

      _totalBytesToReceive = value; 
      UpdateProgress(); 
     } 
    } 

    public ulong BytesReceived 
    { 
     get 
     { 
      return _bytesReceived; 
     } 
     set 
     { 
      if (_bytesReceived == value) 
       return; 

      _bytesReceived = value; 
      UpdateProgress(); 
     } 
    } 

    public int? Progress 
    { 
     get 
     { 
      if (_totalBytesToReceive.HasValue) 
      { 
       return (int)Math.Round((100.0 * _bytesReceived)/_totalBytesToReceive.Value); 
      } 

      return null; 
     } 
    } 

    private void UpdateProgress() 
    { 
     Debug.WriteLine("Progress: {0}", Progress); 
    } 
} 
+0

你自己新建一個緩衝區,這段代碼從內存中申請一個空間並作爲內存中的下載緩衝區。它仍然消耗內存。你寫的只是被HttpClient API封裝 –

相關問題