Flutter开发实战-dio文件下载实现 在开发中,需要下载文件,这里使用的是dio dio 是一个强大的 dart Http 请求库,支持全局配置、Restful api、FORMData、拦截器、 请求取消、Cookie 管理、文件上
在开发中,需要下载文件,这里使用的是dio
dio 是一个强大的 dart Http 请求库,支持全局配置、Restful api、FORMData、拦截器、 请求取消、Cookie 管理、文件上传/下载、超时以及自定义适配器等。
在工程中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文档到电脑,方便收藏和打印~
2024-05-24
2024-05-24
2024-05-24
2024-05-24
2024-05-24
2024-05-24
2024-05-24
2024-05-24
2024-05-24
2024-05-24
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0