美文网首页
flutter分段下载Dio

flutter分段下载Dio

作者: FlowYourHeart | 来源:发表于2019-11-08 15:43 被阅读0次

分块下载的最终速度受设备所在网络带宽、源出口速度、每个块大小、以及分块的数量等诸多因素影响,实际过程中很难保证速度最优。在实际开发中,可以先测试对比后再决定是否使用

此处使用Dio的download方法

import 'dart:io';
import 'package:dio/dio.dart';

class DioDownDataClass
{
/* *
 * Des: 分段下载
 * url:数据、资源的网络地址
 * savePath:下载下来的数据保存的位置
 * onReceivedProgress: 下载进度回调函数
 * */
Future downloadWithChunks(url, savePath, {ProgressCallback onReceivedProgress})
   async {
     //第一次下载数据的长度 byte
     const firstChunkSize = 102;
     //最多几次能全部下完
     const maxChunk = 3;
     //下载的数据总长度
     int total = 0;
     //
     var dio = Dio();

     var progress = <int>[];
     
     createCallback(no) {
       return (int received, _) {
         progress[no] = received;
         if (onReceivedProgress != null && total != 0) {
           onReceivedProgress(progress.reduce((a, b) => a+b), total);
         }
       };
     }
   
  ////start 代表当前块的起始位置,end代表结束位置
//nomber 代表当前是第几块
  Future<Response> downloadChunk(url, start, end, nomber) {
    progress.add(0);
    --end;
    return dio.download(
      url,
      savePath + "temp$nomber",
      onReceiveProgress: createCallback(nomber),
      options: Options(
        //指定请求的内容长度区间
        headers: {"range": "byte=$start-$end"}, 
      )
    );
  }

  //合并文件
  Future mergeTempFiles(chunk) async {
    File f = File(savePath+"temp0");
    IOSink ioSink = f.openWrite(mode: FileMode.writeOnlyAppend);
    //合并临时文件
    for (int i = 1; i < chunk; i ++) {
      File _f = File(savePath + "temp$i") ;
      await ioSink.addStream(_f.openRead());
      await _f.delete();
    }
    await ioSink.close();
    await f.rename(savePath);
  }


  Response response = await downloadChunk(url, 0 ,firstChunkSize, 0);
  if (response.statusCode == 206) { //支持分片下载
    //总长度
     total = int.parse(response.headers.value(HttpHeaders.contentRangeHeader).split("/").last);
     int reserved = total - int.parse(response.headers.value(HttpHeaders.contentLengthHeader));
     int chunk = (reserved / firstChunkSize).ceil() + 1;//分成多少段
     if ( chunk > 1) {
       int chunkSize = firstChunkSize;
       if (chunk > maxChunk + 1) {
         //如果按每次firtstChunkSize需要下载的次数chunk大于自定义最大次数maxChunk+1时
         chunk = maxChunk + 1;
         //不在以每次firstChunkSize下载而是按 次数maxChunk大小chunkSize进行下载
         chunkSize = (reserved / maxChunk).ceil();
       }
       var futures = <Future>[];
       for (var i=0 ;i < maxChunk; i++) {
        //每一次下载的起始位置
         int start = firstChunkSize + i * chunkSize;
         //开始下载文件
         futures.add(downloadChunk(url, start, start+chunkSize, i+1));
       }
       //等待所有分块全部下载完成
       await Future.wait(futures);

     }
     //合并文件 chunk 是分成的块数 futures 元素个数
     await mergeTempFiles(chunk);
  }


}
  

}

分块下载有一个比较使用的场景就是断点续传,可以将文件分为若干个块,然后维护一个下载状态文件用以记录每一个块的状态,这样即使在网络中断后,也可以恢复中断前的状态,具体实现可以自己尝试一下

flutter中文网(11.4 实例:Http分块下载)

相关文章

网友评论

      本文标题:flutter分段下载Dio

      本文链接:https://www.haomeiwen.com/subject/wlfwbctx.html