Flutter如何获取视频文件上传进度 解决Dio上传视频异常问题
问题根因
你当前的实现存在两个核心问题,直接导致文件上传后损坏、体积异常:
- 直接将视频全量读取为字节数组传入Dio,未配置匹配的请求头,Dio会为字节类型的请求体自动添加默认的
Content-Type(通常是application/json或application/octet-stream),和服务器预期的视频格式不匹配,服务器解析时会额外附加错误标识或做转义处理,最终导致文件体积变大、无法播放。 - 全量读取大体积视频到内存的方式本身存在性能问题,极易触发OOM,也无法保证二进制流的完整性。
修复方案
Dio本身支持直接传入文件流进行上传,不需要提前读入全量字节,按你的接口预期选择对应实现即可:
方案1:接口要求裸二进制流上传(常见于预签名URL上传场景)
final videoFile = // 你的视频文件实例 final fileLength = await videoFile.length(); await Dio().put( uploadURL, // 直接传入文件输入流 data: videoFile.openRead(), options: Options( headers: { // 必须指定内容长度,确保进度计算准确、服务器正确接收 Headers.contentLengthHeader: fileLength, // 替换为实际视频对应的MIME类型,不确定可填application/octet-stream Headers.contentTypeHeader: 'video/mp4', }, ), onSendProgress: (int sent, int total) { print('上传进度:${(sent / total * 100).toStringAsFixed(2)}%'); }, );
方案2:接口要求FormData表单格式上传(常见于通用文件上传接口)
final formData = FormData.fromMap({ // 替换为接口要求的文件字段名 'video_file': await MultipartFile.fromFile( videoFile.path, filename: 'upload_${DateTime.now().millisecondsSinceEpoch}.mp4', contentType: MediaType('video', 'mp4'), ), }); await Dio().post( uploadURL, data: formData, onSendProgress: (int sent, int total) { print('上传进度:${(sent / total * 100).toStringAsFixed(2)}%'); }, );
注意事项
- 上传前需确认接口预期的请求方法(PUT/POST)和请求体格式,和实现保持一致即可避免文件损坏问题。
- 如需要自动适配不同视频的MIME类型,可引入
mime包,根据文件后缀自动获取对应类型。 - 只有配置了正确的
Content-Length请求头时,onSendProgress回调的total参数才会返回正确的总文件大小,否则会返回-1。
内容的提问来源于stack exchange,提问作者Subhendu
相关产品推荐
相关产品推荐

