如何在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
相关产品推荐
相关产品推荐

