Flutter中FireStore集合文档创建报错:事务与权限问题及解决方案
搞定Firestore事务创建文档报错+FireStorage授权提示问题
嘿,我来帮你拆解这两个问题,先从你最头疼的Firestore事务报错说起:
一、Firestore事务创建文档的问题分析与正确姿势
你现在用事务创建文档报错,核心原因有俩:一是Firestore事务本来是给已存在的文档做并发更新用的,你当前场景是创建新文档,其实没必要非得用事务;二是大概率你的Firestore安全规则没给已登录用户开放region集合的创建权限。
1. 普通创建文档(不需要事务的场景)
如果你的需求只是新建文档,不需要处理并发覆盖的情况,直接用setData就够了,代码更清爽:
var fileName = _textController.text.toLowerCase(); StorageUploadTask putFile = storage.ref().child("region/$fileName").putFile(_regionImage); UploadTaskSnapshot uploadSnapshot = await putFile.future; // 简化数据结构写法 var regionData = { "label": _textController.text, "picture": { "url": await uploadSnapshot.ref.getDownloadURL(), // 注意:旧版downloadUrl已弃用,用这个更稳妥 "storage": "gs://app-db.appspot.com/region/$fileName" } }; // 直接创建文档 await Firestore.instance.collection("region").document(fileName).setData(regionData); print("instance created");
2. 必须用事务的场景(确保文档不存在才创建)
如果你担心重复创建,必须确保只有文档不存在时才新建,那可以在事务里加个判断,同时一定要配好安全规则:
DocumentReference currentRegion = Firestore.instance.collection("region").document(fileName); await Firestore.instance.runTransaction((transaction) async { DocumentSnapshot freshSnap = await transaction.get(currentRegion); if (!freshSnap.exists) { await transaction.set(currentRegion, regionData); print("instance created"); } else { print("哦豁,这个文档已经存在啦"); } });
3. 重中之重:检查Firestore安全规则
你的报错十有八九是规则卡了!默认规则是允许认证用户读写,但如果你改了默认规则,一定要确保region集合开放权限,比如:
rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /region/{docId} { allow read, write: if request.auth != null; // 已登录用户就能操作 } } }
二、FireStorage无授权token提示的解决
虽然你能正常传文件,但这个提示说明你的Storage规则没正确验证用户身份,改一下规则就好,既安全又能消掉提示:
rules_version = '2'; service firebase.storage { match /b/{bucket}/o { match /region/{allPaths=**} { allow read, write: if request.auth != null; // 仅限已登录用户操作 } } }
最后补个小提醒
- 登录后记得打印
user.uid确认一下,确保用户真的成功认证了,不然权限规则会直接拦截; - 旧版的
uploadSnapshot.downloadUrl已经被弃用啦,换成await uploadSnapshot.ref.getDownloadURL()才是官方推荐的写法哦。
内容的提问来源于stack exchange,提问作者Tree
相关产品推荐
相关产品推荐

