Downloading progress in dart:http
Asked Answered
I

1

8

I'm trying to make a progress bar indicator for a downloading file, but if I add a listener to the StreamedResponse, the piping works, but does to not finish its future.

final client = new http.Client();
http.StreamedResponse response = await client.send(http.Request("GET", Uri.parse('someurl')));

var received = 0;
var length = response.contentLength;

//if I remove this listener, the await below gets completed
var listen = response.stream.listen((List<int> bytes) {
  received += bytes.length;
  print("${(received / length) * 100} %");
});

var sink = downloadFile.openWrite();
await response.stream.pipe(sink);
listen.cancel();
sink.close();

On github they already advised someone that it was supposed to work, but on StreamedResponse docs stays that This should always be a single-subscription stream.. So, adding a listener to calculate the percentage seems to bugs StreamedResponse pipe in someway. Any idea on how to get this to work?

Impact answered 17/6, 2019 at 20:58 Comment(3)
Possible duplicate of Flutter: How to get upload / download progress for http requestsBuskin
use response.stream,map for example and update your received counter thereDiastasis
Sorry, the day has just started here. I was able to make it work yesterday by watching the length of the file that was being written, that worked, but @Diastasis solution with map is easier and will work even if you are not writing into a file, I'll these solutions as answers. Thank you guysImpact
I
14

@pskink comment let me to this solution that works for every type of sink you are using.

  var length = response.contentLength;
  var received = 0;
  var sink = downloadFile.openWrite();

  await response.stream.map((s) {
    received += s.length;
    print("${(received / length) * 100} %");
    return s;
  }).pipe(sink);

another way to accomplish this, if you are writing into a file, is to watch file length

  var length = response.contentLength;
  var sink = downloadFile.openWrite();

  Future.doWhile(() async {
    var received = await downloadFile.length();

    print("${(received / length) * 100} %");
    return received != length;
  });

  await response.stream.pipe(sink);
Impact answered 18/6, 2019 at 12:22 Comment(1)
Can you give a full example?Heterogenous

© 2022 - 2024 — McMap. All rights reserved.