breakPointDownload method

void breakPointDownload({
  1. required String savePath,
  2. ProgressCallback? onReceiveProgress,
  3. Success? success,
  4. Failure? failure,
  5. Completed? completed,
  6. dynamic cancelCallback()?,
})

下载文件 支持断点下载 savePath 文件保存路径 cancelCallback 取消下载时的回调 下载成功 回调success 获取文件本身

Implementation

void breakPointDownload({
  required String savePath,
  ProgressCallback? onReceiveProgress,
  Success? success,
  Failure? failure,
  Completed? completed,
  Function()? cancelCallback,
}) async {

  if (!(await _checkNetWork())) {
    return;
  }

  int downloadStart = 0;
  File file = File(savePath);
  try{
    String url = _path.toString();
    if (isRestfulUrl()) {
      url = NetUtils.restfulUrl(_path.toString(), _params);
    }
    if (file.existsSync()) {
      // downloadStart = file.lengthSync();
      Stream<List<int>> streamFileSize = file.openRead();
      await for (var chunk in streamFileSize) {
        downloadStart += chunk.length;
      }
    }
    _options?.method = _httpType.name;
    /// 以流的方式接收响应数据
    _options = _options?.copyWith(
      responseType: ResponseType.stream,
    );
    ///局部头优先与全局
    if (_headers.isNotEmpty) {
      _options?.headers?.addAll(_headers);
    }
    if (_enableGlobalHeader) {
      _options?.headers ??= {};
      _options?.headers?.addAll(_rxNet._globalHeader);
    }
    _options?.headers?.addAll({"Range": "bytes=$downloadStart-"});
    if(_toFormData){
      _bodyData = FormData.fromMap(_params);
    }
    if(_toBodyData){
      _bodyData = _params;
    }

    final response = await  _rxNet.client!.request<ResponseBody>(
      url,
      options: _options,
      cancelToken: _cancelToken,
      data: _bodyData,
      queryParameters: (isRestfulUrl() || _toFormData || _toBodyData) ? {} : _params,
    );
    onResponse?.call(response);
    RandomAccessFile raf = file.openSync(mode: FileMode.append);
    Stream<Uint8List> stream = response.data!.stream;

    final content= await getContentLength(response);
    final total = int.tryParse(content?.split('/').last??"0")??0;

    final subscription =stream.listen((data) {
        raf.writeFromSync(data);
        downloadStart = downloadStart+data.length;
        if(total<downloadStart){
          onReceiveProgress?.call(total, total);
          return;
        }
        onReceiveProgress?.call(downloadStart, total);
      },
      onDone: () async {
        success?.call(file, SourcesType.net);
        await raf.close();
      },
      onError: (e) async {
         _collectError(e);
         failure?.call(e);
         await raf.close();
      },
      cancelOnError: true
    );

    _cancelToken?.whenCancel.then((_) async {
      await subscription.cancel();
      await raf.close();
      cancelCallback?.call();
    });

  }on DioException catch (error) {
    if(error.response!=null){
      final content= await getContentLength(error.response!);
      final total = int.tryParse(content?.split('/').last??"0")??0;
      if(total<=downloadStart){
        onReceiveProgress?.call(total, total);
        success?.call(file, SourcesType.net);
        return;
      }
    }
    _collectError(error);
    failure?.call(error);
    if (CancelToken.isCancel(error)) {
      cancelCallback?.call();
      return;
    }
  } finally {
    completed?.call();
  }
}