2016-04-05 4 views
0

Ich muss den Download-Fortschritt innerhalb der App für eine beliebige Datei bereitstellen. Ich dachte, ich könnte HttpClient.GetInputStreamAsync Fortschritt verwenden, aber es ist nicht feinkörnig. Die Fortschrittsbenachrichtigung wird sehr selten geliefert. Der folgende Code:Windows Store App HttpClient Fortschritt

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); 
    } 
} 

Ausgänge:

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 

So irgendwann der Zeit die Gesamtzahl der Bytes ist bekannt, zu erhalten aber keine Fortschritte bei der Datei-Download berichtet.

Antwort

0

Da die HttpClient.GetInputStreamAsync nicht Fortschritte bei der Datei-Download unterstützen, können Sie andere Methoden der HttpClient verwenden wie GetAsync und GetBufferAsync .Der folgenden Code des Codes aktualisiert HttpClient.GetAsync zu verwenden.

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"); 

und die Ausgänge

enter image description here

+0

Es macht den Fortschritt berichten, aber es ist auch der gesamte Inhalt in den Speicher zu laden, die ist was ich gerne vermeiden würde. Sorry für die späte Antwort, war beschäftigt. – aguyngueran

0

endete ich unten mit Lösung wie oben:

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

Sie selbst einen Puffer neu, dieser Code ist ein Leerzeichen aus dem Speicher und als Download-Puffer im Speicher. es verbraucht immer noch den Speicher. Was Sie schreiben, wird nur von der HttpClient-API umschlossen –