Flutter Dio取消下载时文件被删除,求保留文件的解决方法
解决方案:保留Dio取消下载后的已下载文件
Dio自带的download方法通过CancelToken取消时,会自动清理临时下载文件——这是因为它内部采用「先写临时文件、完成后重命名到目标路径」的逻辑。要实现停止下载且保留已下载内容,你可以放弃Dio封装好的download方法,改用手动处理响应流的方式:
方法一:手动分块写入文件,自定义取消逻辑
直接通过Dio获取响应流,自己控制文件写入过程,取消时仅停止流订阅,不会删除已写入的内容:
import 'dart:io'; import 'package:dio/dio.dart'; class DownloadHandler { Dio dio = Dio(); File? targetFile; StreamSubscription? streamSubscription; bool _cancelFlag = false; // 启动下载 Future<void> start(String downloadUrl, String savePath) async { targetFile = File(savePath); _cancelFlag = false; try { // 以流形式获取响应,避免大文件占用内存 final response = await dio.get( downloadUrl, options: Options(responseType: ResponseType.stream), ); // 订阅流,分块写入文件 streamSubscription = response.data.stream.listen( (chunk) { if (!_cancelFlag) { targetFile?.writeAsBytes(chunk, mode: FileMode.append); } else { streamSubscription?.cancel(); } }, onDone: () => print("下载完成"), onError: (e) => print("下载出错: $e"), ); } catch (e) { print("请求初始化失败: $e"); } } // 停止下载,保留已下载内容 void cancel() { _cancelFlag = true; streamSubscription?.cancel(); print("下载已停止,已下载内容已保留"); } }
关键说明:
- 用
ResponseType.stream获取响应流,避免一次性加载大文件到内存 - 通过
FileMode.append实现分块写入,确保已下载的字节不会丢失 - 取消时仅标记停止写入并取消流订阅,不会触发Dio内置的文件清理逻辑
注意事项
- 首次下载前如果目标文件已存在,建议先删除或处理(比如实现断点续传时,可先读取已下载长度,请求时设置
Range头) - 确保已申请文件存储权限(Android的
WRITE_EXTERNAL_STORAGE/MANAGE_EXTERNAL_STORAGE,iOS的NSDocumentDirectory访问权限) - 可基于此扩展断点续传:取消后记录已下载文件长度,下次下载时通过
Headers.rangeHeader请求剩余部分
内容的提问来源于stack exchange,提问作者ali ma
相关产品推荐
相关产品推荐

