Flutter中使用Dio实现多文件下载的方法及替代方案咨询
问题
我已经用Dio包实现了单文件下载功能:
Future<void> downloadFile() async { // 请求文件写入权限 bool hasPermission = await _requestWritePermission(); if (!hasPermission) return; Dio dio = Dio(); try { var dir = await getApplicationDocumentsDirectory(); await dio.download(uri, "${dir.path}/eng_json.json", onReceiveProgress: (rec, total) { print("路径 >>> " + "${dir.path}/eng_json.json"); setState(() { downloading = true; }); }); } catch (e) { print("错误 >>> " + e.toString()); } setState(() { downloading = false; print("下载完成"); }); }
现在我需要下载多个文件,请问Dio包是否支持多文件下载?或者Flutter应用中有无处理多文件下载的更佳方案?
回答
Dio完全支持多文件下载,有两种常见实现方式:
- 串行下载:通过循环逐个发起下载请求,适合文件数量不多、需要按顺序下载的场景。代码示例:
Future<void> downloadFilesSerially(List<String> urls, List<String> filenames) async { bool hasPermission = await _requestWritePermission(); if (!hasPermission) return; Dio dio = Dio(); var dir = await getApplicationDocumentsDirectory(); setState(() => downloading = true); for (int i = 0; i < urls.length; i++) { try { await dio.download( urls[i], "${dir.path}/${filenames[i]}", onReceiveProgress: (rec, total) { print("正在下载 ${filenames[i]}: ${((rec/total)*100).toStringAsFixed(2)}%"); } ); print("${filenames[i]} 下载完成"); } catch (e) { print("${filenames[i]} 下载失败: ${e.toString()}"); } } setState(() => downloading = false); print("所有文件下载结束"); }
- 并行下载:用
Future.wait同时发起多个下载请求,效率更高,但要注意控制并发数(比如限制同时下载3-5个),避免请求过多导致异常。代码示例:
Future<void> downloadFilesParallel(List<String> urls, List<String> filenames) async { bool hasPermission = await _requestWritePermission(); if (!hasPermission) return; Dio dio = Dio(); var dir = await getApplicationDocumentsDirectory(); setState(() => downloading = true); // 存储每个下载任务的Future List<Future<void>> downloadTasks = []; for (int i = 0; i < urls.length; i++) { final url = urls[i]; final filename = filenames[i]; downloadTasks.add( dio.download( url, "${dir.path}/$filename", onReceiveProgress: (rec, total) { print("${filename}: ${((rec/total)*100).toStringAsFixed(2)}%"); } ).then((_) { print("${filename} 下载完成"); }).catchError((e) { print("${filename} 下载失败: ${e.toString()}"); }) ); } // 等待所有任务完成 await Future.wait(downloadTasks); setState(() => downloading = false); print("全部下载完成"); }
针对复杂场景的更佳方案
如果需要后台下载、断点续传、下载管理等高级功能,可以使用专门的下载包:
- flutter_downloader:支持多文件后台下载、进度跟踪、断点续传,还能在通知栏显示下载进度,适合需要长时间或后台下载的场景。
- 实现思路:配置下载任务、监听下载状态、处理任务队列,比手动用Dio实现更省心。
另外,不管用哪种方式,都建议:
- 给每个下载任务单独跟踪进度,避免用单一的
downloading变量无法区分每个文件的状态; - 处理网络异常、存储权限变化等边缘情况;
- 大量下载时考虑用Isolate隔离下载逻辑,避免阻塞UI线程。
内容的提问来源于stack exchange,提问作者Jaimin Modi
相关产品推荐
相关产品推荐

