You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.28 22:06:04