downloadFile method

Future downloadFile(
  1. String url, {
  2. required String filename,
  3. required dynamic onProgressUpdate(
    1. int downloaded,
    2. double? percentage,
    3. File? file
    ),
})

url will be used as download url for the file

filename will be used as file name for saving the file in app documents directory

onProgressUpdate will be used as callback function

onProgressUpdate.downloaded will return downloaded bytes

onProgressUpdate.downloaded will return -1 bytes if there is an error while downloading

onProgressUpdate.percentage will return download percentage if available else it will return null

onProgressUpdate.file will return download file

Implementation

Future downloadFile(String url, {required String filename, required Function(int downloaded, double? percentage, File? file) onProgressUpdate}) async {
  if (await isNetworkAvailable() == false) {
    return _noNetwork;
  }

  var httpClient = http.Client();
  var request = http.Request('GET', Uri.parse(_isValidUrl(url) ? url : _apiUrl() + url));
  var response = httpClient.send(request);
  String dir = (await getApplicationDocumentsDirectory()).path;

  List<List<int>> chunks = List.empty(growable: true);
  int downloaded = 0;

  response.asStream().listen((http.StreamedResponse r) {
    r.stream.listen(cancelOnError: true, (List<int> chunk) {
      debugPrint('downloadPercentage: ${r.contentLength != null ? (downloaded / r.contentLength! * 100) : downloaded}');
      onProgressUpdate(downloaded, r.contentLength != null ? (downloaded / r.contentLength! * 100) : null, null);
      chunks.add(chunk);
      downloaded += chunk.length;
    }, onDone: () async {
      debugPrint('downloadPercentage: ${r.contentLength != null ? (downloaded / r.contentLength! * 100) : downloaded}');
      onProgressUpdate(downloaded, r.contentLength != null ? (downloaded / r.contentLength! * 100) : null, null);

      // Save the file
      File file = File('$dir/$filename');
      final Uint8List bytes = Uint8List(downloaded);
      int offset = 0;
      for (List<int> chunk in chunks) {
        bytes.setRange(offset, offset + chunk.length, chunk);
        offset += chunk.length;
      }
      await file.writeAsBytes(bytes);

      onProgressUpdate(downloaded, r.contentLength != null ? (downloaded / r.contentLength! * 100) : null, file);
    }, onError: (error) {
      onProgressUpdate(-1, null, null);
    });
  });
}