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

如何在Flutter中实现Firebase视频上传进度指示器功能

Flutter实现Firebase视频上传进度指示器方案

你当前代码直接await putFile 会等待上传完成才返回结果,无法获取中间进度。Firebase Storage的putFile方法返回的UploadTask实例暴露了snapshotEvents流,可以实时推送上传状态变化,配合状态更新即可实现进度指示器。

  • 第一步:State类中定义进度相关状态变量
class UploadPageState extends State<UploadPage> {
  // 压缩进度 0.0 - 1.0
  double _compressProgress = 0.0;
  // 上传进度 0.0 - 1.0
  double _uploadProgress = 0.0;
  // 是否正在执行上传流程
  bool _isProcessing = false;
  // 上传任务实例,可用于取消上传
  UploadTask? _uploadTask;
}
  • 第二步:修改压缩+上传逻辑,监听进度事件
Future<void> uploadVideo() async {
  setState(() {
    _isProcessing = true;
    _compressProgress = 0.0;
    _uploadProgress = 0.0;
  });
  try {
    // 压缩视频,监听压缩进度
    MediaInfo? compressVideo = await VideoCompress.compressVideo(
      videoPath,
      quality: VideoQuality.Res640x480Quality,
      includeAudio: true,
      // 监听压缩进度
      onProgress: (progress) {
        setState(() {
          _compressProgress = progress;
        });
      },
    );
    if (compressVideo?.path == null) {
      throw Exception("视频压缩失败");
    }
    print('video Compressing Done');

    // 拿到上传任务实例,不要直接await
    _uploadTask = FirebaseStorage.instance
        .ref()
        .child("videos/${Me.get().uid}/${videoDoc.id}")
        .putFile(File(compressVideo!.path!));

    // 监听上传进度
    _uploadTask!.snapshotEvents.listen((snapshot) {
      setState(() {
        _uploadProgress = snapshot.bytesTransferred / snapshot.totalBytes;
      });
    }, onError: (e) {
      throw e;
    });

    // 等待上传完成
    await _uploadTask;
    print('video Uploading Done');

    final videoUrl = await _uploadTask!.ref.getDownloadURL();
    showToast("Upload Successful");
  } catch (e) {
    showToast("上传失败:${e.toString()}");
  } finally {
    setState(() {
      _isProcessing = false;
      _uploadTask = null;
    });
  }
}
  • 第三步:构建进度指示器UI
@override
Widget build(BuildContext context) {
  return Scaffold(
    body: Center(
      child: _isProcessing ? Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          const Text("视频压缩中"),
          LinearProgressIndicator(value: _compressProgress),
          const SizedBox(height: 20),
          const Text("视频上传中"),
          LinearProgressIndicator(value: _uploadProgress),
          // 可选:取消上传按钮
          TextButton(
            onPressed: () {
              _uploadTask?.cancel();
              setState(() => _isProcessing = false);
            },
            child: const Text("取消上传"),
          )
        ],
      ) : ElevatedButton(
        onPressed: uploadVideo,
        child: const Text("上传视频"),
      ),
    ),
  );
}

注意事项

  • 所有异步操作需要做好异常捕获,避免用户取消上传、网络中断等场景触发崩溃
  • 进度数值范围为0-1,直接传入LinearProgressIndicator的value参数即可自动渲染进度,如果要展示百分比文本,直接将_uploadProgress * 100取整即可
  • 如果不需要展示压缩进度,可以省略压缩进度的监听逻辑,仅保留上传进度监听即可

内容的提问来源于stack exchange,提问作者Happy Sinha

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 14:48:05