2016-04-05 104 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封装 –

相关问题