iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >flutter开发实战-dio文件下载实现
  • 657
分享到

flutter开发实战-dio文件下载实现

flutterdio下载 2023-08-23 09:08:34 657人浏览 泡泡鱼
摘要

Flutter开发实战-dio文件下载实现 在开发中,需要下载文件,这里使用的是dio dio 是一个强大的 dart Http 请求库,支持全局配置、Restful api、FORMData、拦截器、 请求取消、Cookie 管理、文件上

Flutter开发实战-dio文件下载实现

在开发中,需要下载文件,这里使用的是dio
dio 是一个强大的 dart Http 请求库,支持全局配置、Restful api、FORMData、拦截器、 请求取消、Cookie 管理、文件上传/下载、超时以及自定义适配器等。

在这里插入图片描述

一、引入dio

在工程中pubspec.yaml引入dio

dio: ^5.1.1  dio_cookie_manager: ^3.0.0

二、代码实现

我们对dio进行封装

// 定义枚举,请求方法枚举enum HttpApiMethod {  GET,  POST,  DELETE,  PUT,}// 网络请求的成功与失败// 上传typedef OnUploaded = void Function(Map<String, dynamic> result);// 下载进度typedef OnDownloadProgress = void Function(int count, int total);// 下载成功typedef OnDownloaded = void Function();// 请求成功typedef OnSuccess = void Function(ResponseData responseData);// 请求失败typedef OnFailure = void Function(ApiHttpError error);// 请求Apiclass HttpApi {  // 网络请求库dio  Dio dio = Dio(BaseOptions(    // connectTimeout: 60000, // 连接服务器超时时间,单位是毫秒.    // receiveTimeout: 10000, // 响应流上前后两次接受到数据的间隔,单位为毫秒, 这并不是接收数据的总时限    headers: {      HttpHeaders.acceptHeader: "text/plain,"          "text/plain,"          "multipart/form-data,"          "application/JSON,"          "text/html,"          "image/jpeg,"          "image/png,"          "application/octet-stream,"          "text/json,"          "text/javascript,"          "text/html",    },  ));  // 私有构造函数  HttpApi._internal();  //保存单例  static HttpApi _singleton = HttpApi._internal();  //工厂构造函数  factory HttpApi() => _singleton;  /// 配置请求头header  ///   /// The request Content-Type. The default value is 'application/json; charset=utf-8'.  //   /// If you want to encode request body with 'application/x-www-form-urlencoded',  //   /// you can set [Headers.formUrlEncodedContentType], and [Dio]  //   /// will automatically encode the request body.  Future<void> configHeaders(      String requestUrl, Map<String, dynamic>? params) async {    dio.options.headers['Content-Type'] = Headers.jsonContentType;    LoggerManager().info(        "requestUrl:${requestUrl} dio.options.headers:${dio.options.headers}");  }  get(String url, ApiServiceDomain serviceDomain,      {Map<String, dynamic>? params, OnSuccess? success, OnFailure? failure}) {    doRequest(url, serviceDomain, HttpApiMethod.GET,        params: params, success: success, failure: failure);  }  post(String url, ApiServiceDomain serviceDomain,      {Map<String, dynamic>? params, OnSuccess? success, OnFailure? failure}) {    doRequest(url, serviceDomain, HttpApiMethod.POST,        params: params, success: success, failure: failure);  }  // 请求服务器  // params,参数  // 请求成功  // 请求失败  Future<void> doRequest(      String url, ApiServiceDomain serviceDomain, HttpApiMethod method,      {Map<String, dynamic>? params,      OnSuccess? success,      OnFailure? failure}) async {    String requestUrl = getRequestUrl(url, serviceDomain);    try {      /// 可以添加header      await configHeaders(requestUrl, params);      Response? response;      switch (method) {        case HttpApiMethod.GET:          {            // get请求            if (params != null && params.isNotEmpty) {              response = await dio.get(requestUrl,                  queryParameters: params,                  options: Options(contentType: Headers.jsonContentType));              LoggerManager()                  .debug("await dio.get response:$response,params:$params");            } else {              response = await dio.get(requestUrl,                  options: Options(contentType: Headers.jsonContentType));            }            break;          }        case HttpApiMethod.POST:          {            // post请求            String? contentType = Headers.formUrlEncodedContentType;            if (params != null && params.isNotEmpty) {              response = await dio.post(requestUrl,                  data: params, options: Options(contentType: contentType));              LoggerManager()                  .debug("await dio.post response:$response,params:$params");            } else {              response = await dio.post(requestUrl,                  options: Options(contentType: contentType));            }            break;          }        // case HttpApiMethod.PUT: {        //   break;        // }        // case HttpApiMethod.DELETE: {        //   break;        // }        default:      }      LoggerManager().debug('doRequest: $response, params:$params');      if (response != null) {        Map<String, dynamic> result = json.decode(response.toString());        assert(() {          // assert只会在debug模式下执行,release模式下不会执行          // 打印信息          LoggerManager().debug('''api: $requestUrl\nresult: $result''');          return true;        }());        ResponseData responseData = ResponseData.fromJson(result);        if (responseData.status == 0) {          if (success != null) {            //返回请求数据            success(responseData);          }        } else {          //返回失败信息          ApiHttpError apiHttpError = getErrorRequestResponseData(responseData);          LoggerManager().debug("apiHttpError:${apiHttpError.toString()}");          LoggerManager().error('''api: $requestUrl\nresult: $result''');          if (failure != null) {            failure(apiHttpError);          }        }      } else {        // 没有获得response,failure        ApiHttpError apiHttpError =            ApiHttpError(ApiHttpErrorType.Default, "请求失败!");        LoggerManager().debug("apiHttpError:${apiHttpError.toString()}");        if (failure != null) {          failure(apiHttpError);        }      }    } on DioError catch (e, s) {      // catch到异常,failure      // The request was made and the server responded with a status code      // that falls out of the range of 2xx and is also not 304.      LoggerManager()          .error("doRequest api: $requestUrl, dioError:${e.message}, s:$s");      ApiHttpError apiHttpError = getRequestFailure(e.response, e.type);      LoggerManager().debug("apiHttpError:${apiHttpError.toString()}");      if (failure != null) {        failure(apiHttpError);      }    } catch (e) {      // 可以捕获任意异常      ApiHttpError apiHttpError =          ApiHttpError(ApiHttpErrorType.Default, "${e.toString()}");      if (failure != null) {        failure(apiHttpError);      }    }  }  // 上传文件(图片)  doUploadFile(String url, UploadFileInfo fileInfo,      {Map<String, dynamic>? params,      OnUploaded? uploaded,      OnFailure? failure}) async {    try {      String timeStamp = DateTime.now().millisecondsSinceEpoch.toString();      Map<String, dynamic> fromParams = Map();      if (params != null && params.isNotEmpty) {        fromParams.addAll(params);      }      fromParams["file"] = await MultipartFile.fromFile(fileInfo.file.path,          filename: '${fileInfo.key}-${timeStamp}.jpg');      FormData formData = FormData.fromMap(fromParams);      Response? response = await dio.post(url, data: formData);      assert(() {        // assert只会在debug模式下执行,release模式下不会执行        // 打印信息        LoggerManager().error('''api: $url\nresult: $response''');        return true;      }());      if (response != null) {        Map<String, dynamic> result = json.decode(response.toString());        assert(() {          // assert只会在debug模式下执行,release模式下不会执行          // 打印信息          LoggerManager().debug('''api: $url\nresult: $result''');          return true;        }());        if (response.statusCode == 200) {          if (uploaded != null) {            uploaded(result);          }        } else {          //返回失败信息          LoggerManager().error('''api: $url\nresult: $result''');          ApiHttpError apiHttpError =              ApiHttpError(ApiHttpErrorType.Default, "请求失败!");          if (failure != null) {            failure(apiHttpError);          }        }      } else {        //返回失败信息        // 没有获得response,failure        ApiHttpError apiHttpError =            ApiHttpError(ApiHttpErrorType.Default, "请求失败!");        if (failure != null) {          failure(apiHttpError);        }      }    } on DioError catch (e, s) {      // catch到异常,failure      LoggerManager().error("doUploadFile api: $url, dioError:$e, s:$s");      ApiHttpError apiHttpError = getRequestFailure(e.response, e.type);      if (failure != null) {        failure(apiHttpError);      }    } catch (e) {      // 可以捕获任意异常      ApiHttpError apiHttpError =          ApiHttpError(ApiHttpErrorType.Default, "${e.toString()}");      if (failure != null) {        failure(apiHttpError);      }    }  }  // 下载文件  void doDownload(String url, String savePath,      {required CancelToken cancelToken,      Map<String, dynamic>? params,      dynamic? data,      Options? options,      OnDownloadProgress? progress,      OnDownloaded? completion,      OnFailure? failure}) async {    try {      dio.download(        url,        savePath,        queryParameters: params,        cancelToken: cancelToken,        onReceiveProgress: (int count, int total) {          if (total != -1) {            if (!cancelToken.isCancelled) {              double downloadRatio = (count / total);              if (downloadRatio == 1) {                if (completion != null) {                  completion();                }              } else {                if (progress != null) {                  progress(count, total);                }              }            }          } else {            ApiHttpError apiHttpError =                ApiHttpError(ApiHttpErrorType.Default, "无法获取文件大小,下载失败!");            if (failure != null) {              failure(apiHttpError);            }          }        },      );    } on DioError catch (e) {      ApiHttpError apiHttpError =          ApiHttpError(ApiHttpErrorType.Default, e.toString());      if (CancelToken.isCancel(e)) {        apiHttpError = ApiHttpError(ApiHttpErrorType.Cancel, "下载已取消!");      } else {        if (e.response != null) {          apiHttpError = getRequestFailure(e.response, e.type);        } else {          apiHttpError = ApiHttpError(ApiHttpErrorType.Default, e.message??"");        }      }      if (failure != null) {        failure(apiHttpError);      }    } on Exception catch (e) {      // EasyLoading.showError(e.toString());      ApiHttpError apiHttpError =          ApiHttpError(ApiHttpErrorType.Default, e.toString());      if (failure != null) {        failure(apiHttpError);      }    } catch (e) {      // 可以捕获任意异常      ApiHttpError apiHttpError =          ApiHttpError(ApiHttpErrorType.Default, "${e.toString()}");      if (failure != null) {        failure(apiHttpError);      }    }  }  // 根据服务器来拼接服务器具体地址  String getRequestUrl(String url, ApiServiceDomain serviceDomain) {    String requestUrl = url;    return requestUrl;  }  ApiHttpError getErrorRequestResponseData(ResponseData responseData) {    //返回失败信息    ApiHttpError apiHttpError =        ApiHttpError(ApiHttpErrorType.Default, responseData.errorMsg);    if (kNeedAuthLoginErrorCode == responseData.errorCode) {      apiHttpError = ApiHttpError(ApiHttpErrorType.Auth, responseData.errorMsg);    }    return apiHttpError;  }  ApiHttpError getRequestFailure(      Response? response, DioErrorType dioErrorType) {    LoggerManager()        .error("getRequestFailure: $response, dioError:$dioErrorType");    ApiHttpErrorType errorType = ApiHttpErrorType.Default;    String errorMessage = "请求失败!";    if (response != null) {      if (dioErrorType == DioErrorType.connectionTimeout) {        errorType = ApiHttpErrorType.netWork;        errorMessage = "网络链接异常!";      } else if (dioErrorType == DioErrorType.sendTimeout) {        errorType = ApiHttpErrorType.Timeout;        errorMessage = "网络链接异常!";      } else if (dioErrorType == DioErrorType.receiveTimeout) {        errorType = ApiHttpErrorType.Timeout;        errorMessage = "网络链接异常!";      } else if (dioErrorType == DioErrorType.badResponse) {        // When the server response, but with a incorrect status, such as 404, 503...        if (response != null) {          if (response.statusCode == 401) {            errorType = ApiHttpErrorType.Auth;            errorMessage = "认证失败!";          } else if (response.statusCode == 400) {            errorType = ApiHttpErrorType.BadRequest;            errorMessage = "无效请求!";          } else if (response.statusCode == 404) {            errorType = ApiHttpErrorType.NotFound;            errorMessage = "访问的资源丢失了!";          } else if (response.statusCode == 405) {            // 请求的方法错误            errorType = ApiHttpErrorType.BadParamHeader;            errorMessage = "参数出错!";          } else if (response.statusCode! >= 500) {            errorType = ApiHttpErrorType.BadRequest;            errorMessage = "服务器居然累倒了!";          }        }      } else if (dioErrorType == DioErrorType.cancel) {        errorType = ApiHttpErrorType.Cancel;        errorMessage = "请求已经取消";      }    } else {      errorType = ApiHttpErrorType.NetWork;      errorMessage = "网络链接异常!";    }    ApiHttpError apiHttpError = ApiHttpError(errorType, errorMessage);    return apiHttpError;  }}/// 上传的文件类class UploadFileInfo {  File file;  String key;  UploadFileInfo({required this.file, required this.key});}

文件下载页面实现实例

class DownloadPage extends StatefulWidget {  const DownloadPage({    Key? key,    this.messages,    this.uniqueId,    this.arguments,  }) : super(key: key);  final Object? arguments;  final String? messages;  final String? uniqueId;    State<DownloadPage> createState() => _DownloadPageState();}class _DownloadPageState extends State<DownloadPage> {  String _downloadPath =      'https://dl.Google.com/chrome/Mac/stable/GGRO/googlechrome.dmg';  double _downloadRatio = 0.0;  String _downloadIndicator = '0.00%';  late String _destPath;  late CancelToken _token;  bool _downloading = false;    void initState() {    getTemporaryDirectory()        .then((tempDir) => {_destPath = tempDir.path + 'googlechrome.dmg'});    super.initState();  }  void _downloadFile() {    if (_downloading == true) {      return;    }    _token = CancelToken();    _downloading = true;    HttpApi().doDownload(_downloadPath, _destPath, cancelToken: _token,        progress: (int received, int total) {      // 下载进度      setState(() {        _downloadRatio = (received / total);        if (_downloadRatio == 1) {          _downloading = false;        }        _downloadIndicator = (_downloadRatio * 100).toStringAsFixed(2) + '%';      });    }, completion: () {      // 下载成功      _downloading = false;      FlutterLoadingHud.showToast(message: "\"下载完成\"");    }, failure: (error) {      // 下载出错      _downloading = false;      FlutterLoadingHud.showToast(message: error.message);    });  }  void _cancelDownload() {    if (_downloadRatio < 1.0) {      _token.cancel();      _downloading = false;      setState(() {        _downloadRatio = 0;        _downloadIndicator = '0.00%';      });    }  }  void _deleteFile() {    try {      File downloadedFile = File(_destPath);      if (downloadedFile.existsSync()) {        downloadedFile.delete();      } else {        FlutterLoadingHud.showToast(message: "文件不存在");      }    } catch (e) {      FlutterLoadingHud.showToast(          message: "${e.toString()}");    }  }    Widget build(BuildContext context) {    return Scaffold(      resizeToAvoidBottomInset: false,      appBar: AppBar(        leading: AppBarIconButton(          icon: Icon(Icons.arrow_back_iOS),          onPressed: () => {NavigatorRoute.pop()},        ),        centerTitle: true,        backgroundColor: ColorUtil.hexColor(0xffffff),        foregroundColor: ColorUtil.hexColor(0x777777),        elevation: 0,        title: Text(          "下载示例",          textAlign: TextAlign.center,          softWrap: true,          style: TextStyle(            fontSize: 17,            color: ColorUtil.hexColor(0x333333),            fontWeight: FontWeight.w600,            fontStyle: FontStyle.normal,            decoration: TextDecoration.none,          ),        ),        shadowColor: ColorUtil.hexColor(0xffffff),        toolbarHeight: 44.0,        bottomOpacity: 0.0,      ),      body: Container(        color: ColorUtil.hexColor(0xf7f7f7),        alignment: Alignment.center,        padding: EdgeInsets.all(10),        child: Column(          mainAxisAlignment: MainAxisAlignment.center,          children: [            Row(              children: [                _buildDownloadButton(),                TextButton(                  child: Text('取消'),                  onPressed: () {                    _cancelDownload();                  },                ),                TextButton(                  child: Text(                    '删除',                    style: TextStyle(                        color: !_downloading ? Colors.red : Colors.grey),                  ),                  onPressed: (!_downloading ? _deleteFile : null),                  style: ButtonStyle(),                ),              ],            ),            SizedBox(              height: 25,            ),            Row(children: [              Expanded(                child: LinearProgressIndicator(                  backgroundColor: Colors.grey[600],                  value: _downloadRatio,                ),              ),              SizedBox(                width: 5,              ),              Text(                _downloadIndicator,                style: TextStyle(color: Colors.black, fontSize: 12.0),              ),            ]),          ],        ),      ),    );  }  Widget _buildDownloadButton() {    return ButtonWidget(      onPressed: () {        _downloadFile();      },      child: Text(        "下载文件",        textAlign: TextAlign.center,        softWrap: true,        style: TextStyle(          fontSize: 16,          fontWeight: FontWeight.w400,          fontStyle: FontStyle.normal,          color: ColorUtil.hexColor(0xffffff),          decoration: TextDecoration.none,        ),      ),      height: 40,      width: 100.0,      highlightedColor: ColorUtil.hexColor(0xff462e),      bGColor: ColorUtil.hexColor(0xff462e),      bgHighlightedColor: ColorUtil.hexColor(0xff462e, alpha: 0.75),      enabled: true,      bgDisableColor: Colors.grey,      borderRadius: 22.0,    );  }}

三、小结

flutter开发实战-dio文件下载实现,封装dio下载功能,实现文件下载

学习记录,每天不停进步。

来源地址:https://blog.csdn.net/gloryFlow/article/details/131658621

--结束END--

本文标题: flutter开发实战-dio文件下载实现

本文链接: https://www.lsjlt.com/news/378458.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作