Flutter从Firebase Storage加载图片失败,报ProgressEvent错误如何解决?
解决Flutter从Firebase Storage加载图片失败的问题
问题描述
使用Flutter开发应用时,尝试从Firebase Storage获取图片但无法显示,相关代码及报错信息如下:
代码
import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:flutter/material.dart'; import '../widgets/action_bar.dart'; class HomeTab extends StatelessWidget { final CollectionReference _productRef = FirebaseFirestore.instance.collection("products"); @override Widget build(BuildContext context) { return Container( child: Stack( children: [ FutureBuilder<QuerySnapshot>( future: _productRef.get(), builder: (context , snapshot){ if(snapshot.hasError){ return Scaffold( body: Center( child: Text("Error ${snapshot.error}"), ), ); } if(snapshot.connectionState == ConnectionState.done){ return ListView( children: snapshot.data!.docs.map((document) { return Container( child: Image.network( "${(document.data() as Map<String, dynamic>)["image"][0]}", ), //child: Text("name: ${(document.data() as Map<String, dynamic>)["name"]}"), ); }).toList(), ); } return Scaffold( body: Center( child: CircularProgressIndicator(), ), ); } ), ] ), ); } }
报错信息
══╡ EXCEPTION CAUGHT BY IMAGE RESOURCE SERVICE ╞════════════════════════════════════════════════════ The following ProgressEvent$ object was thrown resolving an image codec: [object ProgressEvent] When the exception was thrown, this was the stack Image provider: NetworkImage("gs://second-ecommerce-b5666.appspot.com/IMG-20230520-WA0256.jpg", scale: 1) Image key: NetworkImage("gs://second-ecommerce-b5666.appspot.com/IMG-20230520-WA0256.jpg", scale: 1) ════════════════════════════════════════════════════════════════════════════════════════════════════ Another exception was thrown: [object ProgressEvent] Another exception was thrown: [object ProgressEvent]
问题原因
Image.network仅支持加载HTTP/HTTPS协议的公开网络链接,而代码中使用的gs://开头的路径是Firebase Storage的内部存储桶路径,并非可直接访问的网络地址,因此无法被解析加载。
解决方法
方法1:直接替换为公开HTTP下载链接
- 打开Firebase控制台,进入Storage页面找到目标图片文件
- 点击文件右侧的更多选项,选择「获取下载链接」
- 将生成的HTTPS链接替换到Firestore文档中
image字段的对应值,之后Image.network即可正常加载图片
方法2:通过Firebase Storage SDK动态获取下载URL
- 先在
pubspec.yaml中添加firebase_storage依赖:
dependencies: flutter: sdk: flutter cloud_firestore: ^latest_version firebase_storage: ^latest_version
- 修改代码,通过SDK获取可访问的下载URL:
import 'package:cloud_firestore/cloud_firestore.dart'; import 'package:flutter/material.dart'; import 'package:firebase_storage/firebase_storage.dart'; import '../widgets/action_bar.dart'; class HomeTab extends StatelessWidget { final CollectionReference _productRef = FirebaseFirestore.instance.collection("products"); final FirebaseStorage _storage = FirebaseStorage.instance; // 获取文件下载URL的方法 Future<String> getDownloadUrl(String filePath) async { final ref = _storage.ref().child(filePath); return await ref.getDownloadURL(); } @override Widget build(BuildContext context) { return Container( child: Stack( children: [ FutureBuilder<QuerySnapshot>( future: _productRef.get(), builder: (context, snapshot) { if (snapshot.hasError) { return Scaffold( body: Center( child: Text("Error ${snapshot.error}"), ), ); } if (snapshot.connectionState == ConnectionState.done) { return ListView( children: snapshot.data!.docs.map((document) { // 提取存储桶后的文件路径 String imagePath = (document.data() as Map<String, dynamic>)["image"][0] .replaceFirst("gs://second-ecommerce-b5666.appspot.com/", ""); // 嵌套FutureBuilder获取下载URL return FutureBuilder<String>( future: getDownloadUrl(imagePath), builder: (context, urlSnapshot) { if (urlSnapshot.connectionState == ConnectionState.done && urlSnapshot.hasData) { return Container( child: Image.network(urlSnapshot.data!), ); } // URL加载中显示指示器 return Container( height: 100, child: Center(child: CircularProgressIndicator()), ); }, ); }).toList(), ); } return Scaffold( body: Center( child: CircularProgressIndicator(), ), ); }, ), ], ), ); } }
注意事项
- 使用方法2时,需确保Firebase Storage的安全规则允许当前用户读取文件。开发环境可临时使用宽松规则测试:
rules_version = '2'; service firebase.storage { match /b/{bucket}/o { match /{allPaths=**} { allow read, write: if true; } } }
- 正式环境必须设置严格的权限规则,防止数据泄露。
内容的提问来源于stack exchange,提问作者amal
相关产品推荐
相关产品推荐

