'resume downloading messes up the file

i'm trying to download a large file and be able to resume the downloading where it left off,

i'm currently using this code to achieve this

//downloadUntil is a large number (~10GB) so that if we don't specify
//our own number the http will automatically trim it to the file size.

downloadFile(String url, {int downloadFrom=0, int downloadUntil=99999999999 }) async {
  var httpClient = http.Client();
  var request = new http.Request('GET', Uri.parse(url));
  
  //we will add Range to the header, downloadFrom will be zero
  //if the file is being downloaded for the first time,
  //and it will be a different number if we're resuming the download.
  request.headers.addAll({'Range': 'bytes=$downloadFrom-$downloadUntil'});
  var response = httpClient.send(request);

  //create a RandomAccessFile object so that we can write the chunks to the file.
  RandomAccessFile raf = await File(downloadPath).open(mode: FileMode.write);

  //this variable will keep track of the downloaded bytes,
  //we use it to offset the file when writing to it.
  int downloaded = downloadFrom;

  response.asStream().listen((http.StreamedResponse r) {
    r.stream.listen((List<int> chunk) async {
      //print the percentage
      debugPrint('downloadPercentage: ${downloaded / r.contentLength * 100}');

      //offsetting the file
      raf.setPositionSync(downloaded);
      //then write the downloaded chunk to the file
      raf.writeFromSync(chunk);
 
      //update the downloaded variable
      downloaded += chunk.length;
    }, onDone: () async {
      debugPrint('download completed');
      return;
    });
  });
}

the file works fine when for example i have a 150MB video file and download only 50MB by executing this code:-

downloadFile("https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4", downloadUntil: 50000000//~50MB);

the video file works fine, i can watch the downloaded part, everything works as intended.

then i execute this code to download the remaining bytes:-

downloadFile("https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4", downloadFrom: 50000000//~50MB);

then the video file doesn't work anymore, it gets unseekable stream,

i also tried to download the file by downloadFrom:49999900 and replace some of the downloaded bytes to avoid skipping any bytes, also tried downloadFrom: 50000001 to avoid replacing any downloaded bytes, none of them worked.

what am i doing wrong here?



Solution 1:[1]

You are opening the file with FileMode.write which overwrites all the existing bytes saved by the previous download. Change it to FileMode.append and you are good to go.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Tyler2P