Dart通过Http Range头实现断点续传后视频文件损坏无法播放问题求助
断点续传代码错误分析与修复
核心问题点
文件打开模式错误
你每次调用下载函数时都使用FileMode.write模式打开文件,该模式会直接截断原有文件,将已有内容全部清空。第二次续传时,前50MB的已下载内容直接被清空,你再从50MB偏移位置写入新数据,文件前半部分全为空值,自然无法正常播放。文件句柄未正常关闭
下载完成的onDone回调中没有关闭RandomAccessFile对象,内存中未刷入磁盘的缓存数据会丢失,也可能导致文件结构损坏。缺少Range请求校验
发送Range断点请求后,没有校验服务器是否返回206 Partial Content状态码,如果服务器不支持断点续传返回了200全量响应,你的偏移写入逻辑会直接出错。异步逻辑存在隐患
Stream回调嵌套执行同步IO操作,没有对异步流程做正确控制,可能出现写入顺序错乱的问题。
修复后的代码
downloadFile(String url, {int downloadFrom=0, int downloadUntil=99999999999 }) async { var httpClient = http.Client(); try { var request = http.Request('GET', Uri.parse(url)); request.headers.addAll({'Range': 'bytes=$downloadFrom-$downloadUntil'}); var response = await httpClient.send(request); // 校验断点续传是否生效 if (response.statusCode != 206) { throw Exception("服务器不支持断点续传"); } // 下载从头开始就用write模式截断旧文件,续传用writeOnlyCreate保留已有内容不截断 RandomAccessFile raf = await File(downloadPath).open( mode: downloadFrom == 0 ? FileMode.write : FileMode.writeOnlyCreate ); int downloaded = downloadFrom; // 用await for处理流避免回调嵌套问题 await for (var chunk in response.stream) { debugPrint('当前段下载进度: ${downloaded / (downloadFrom + response.contentLength!) * 100}'); await raf.setPosition(downloaded); await raf.writeFrom(chunk); downloaded += chunk.length; } debugPrint('下载完成'); await raf.close(); } catch (e) { debugPrint('下载出错: $e'); rethrow; } finally { httpClient.close(); } }
额外注意点
- 第一次下载完成后一定要确保文件已经正常关闭,再执行续传操作
- 如果需要计算全文件的下载进度,可以先发送一次HEAD请求获取文件总大小,再用已下载的字节数除以总大小计算
内容的提问来源于stack exchange,提问作者kurdish sage
相关产品推荐
相关产品推荐

