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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 06:38:47