Flutter应用下载大文件卡顿停滞于99%,求优化方案
解决大文件下载加密后写入卡顿问题
问题场景
我编写了一个Dart脚本,用于加密视频并下载至应用存储中。下载小文件时无任何问题,但下载大文件时,应用会卡在99%,需要约2分钟才能将文件保存到应用存储。
问题根源
当前实现的核心问题是全量内存处理逻辑:
- 下载时将整个文件的字节数组一次性加载到内存(
ResponseType.bytes),大文件会占用极大内存空间,引发内存压力 - 下载完成后才执行全量加密、全量写入操作,这两个同步操作会阻塞主线程,导致UI无响应
onReceiveProgress仅跟踪下载阶段进度,下载完成后(进度接近100%),后续加密写入阶段无进度反馈,造成"卡住"的视觉效果
解决方案:流式分块处理
改用边下载、边加密、边写入的流式分块逻辑,既降低内存占用,又能持续更新进度,避免卡顿。同时调整AES加密模式为支持流式操作的CTR模式,确保分块加密的正确性。
修改后代码实现
1. 调整加密配置(改用CTR模式)
class MyEncrypt{ static final myKey = esc.Key.fromUtf8('TechWithVPTechWithVPTechWithVP12'); static final myIv = esc.IV.fromUtf8('VivekPanacha1122'); // 改用CTR模式,支持流式分块加密,避免CBC模式的链式依赖问题 static final myEncrypt = esc.Encrypter(esc.AES(myKey, mode: esc.AESMode.ctr)); }
2. 流式下载+加密+写入逻辑
final String url = streamInfo.url.toString(); final dir = await getApplicationDocumentsDirectory(); final savePath = '${dir.path}/${widget.lessoneName.toString()}.aes'; final file = File(savePath); final fileSink = file.openWrite(); print("Downloading..."); int totalBytes = 0; int processedBytes = 0; await dio.download( url, savePath, options: Options( responseType: ResponseType.stream, followRedirects: false, ), onReceiveProgress: (received, total) { if (total != -1) totalBytes = total; // 实时更新下载进度 setState(() { progress = received / totalBytes; }); }, onReceiveData: (chunk) async { // 分块加密当前数据 final encryptedChunk = _encryptData(chunk); // 分块写入文件 await fileSink.add(encryptedChunk); processedBytes += chunk.length; // 可选:更新包含加密写入的整体进度,让进度条更平滑 setState(() { progress = processedBytes / totalBytes; }); }, ); // 确保所有数据写入完成后关闭流 await fileSink.close(); print("File downloaded successfully");
3. 分块加密方法(无需大幅修改)
List<int> _encryptData(List<int> bytes) { final encrypted = MyEncrypt.myEncrypt.encryptBytes(bytes, iv: MyEncrypt.myIv); return encrypted.bytes; }
优化说明
- 内存优化:分块处理避免了大字节数组占用内存,降低OOM风险
- 进度反馈:加密写入阶段也能更新进度,不会出现长时间卡在99%的情况
- 加密正确性:CTR模式支持流式加密,分块加密结果与全量加密一致,解密时可正常还原
内容的提问来源于stack exchange,提问作者Ahmed Naseem
相关产品推荐
相关产品推荐

