Google Firebase 实战教学 - Streamlit、Bucket、Firebase

今天抽空研究了一下 Google Firebase,顺手做了一个 Python (Streamlit) 的小 Demo,感觉非常强大。写这篇博客记录一下搭建过程,顺便聊聊其中几个有意思的技术点。

1. 什么是 Firebase?它和 SQL、Storage 有啥区别?

很多人可能会问:既然已经有了 Cloud SQL (数据库) 和 Cloud Storage (对象存储),Google 为什么要搞一个 Firebase?

其实它们定位完全不同:

  • Cloud SQL (MySQL/PostgreSQL):是传统的关系型数据库,适合存结构化严谨的数据,但通常需要你自己写后端 API 来读写。
  • Cloud Storage (Bucket):就是个云盘,用来存文件(图片、视频、文本),不适合存细粒度的业务数据。
  • Firebase (Firestore) :它是一个 BaaS (Backend-as-a-Service) 平台。
    • 特点:它既是数据库,又自带后端逻辑。
    • 核心优势 :支持 Real-time (实时同步)。你在数据库里改个字,客户端不需要刷新,毫秒级自动更新。

2. 实战 Demo:搭建 Python 实时留言板

今天我们就用 Python + Streamlit + Firebase 快速撸一个小项目。

第一步:进入 Firebase 控制台

点击进入标准控制台:👉 https://console.firebase.google.com/

找到并进入你的项目。

第二步:创建数据库 (Firestore)

  1. 在左侧菜单栏,点击 构建 (Build) -> Firestore Database
  2. 点击 创建数据库 (Create Database)
  3. 位置 :保持默认(通常是 us-central1)。
  4. 安全规则 (重点) :一定要选 "以测试模式开始" (Start in test mode)
    • 注意:这一步很重要,否则你的程序会因为没有权限而报错。
  5. 点击 Create,等待几秒即可。

第三步:获取"通行证" (key.json)

这是很多人容易卡住的一步,Cloud Console 里比较乱,建议在 Firebase Console 操作:

  1. 点击左上角 项目概览 (Project Overview) 旁边的 齿轮图标 ⚙️ -> 项目设置
  2. 点击顶部的 服务账号 (Service accounts) 选项卡。
  3. 点击下方的 生成新的私钥 (Generate new private key) 按钮。
  4. 下载下来的 .json 文件,重命名为 key.json,并放到你的项目文件夹里。

3. 上代码

确保你的环境已经安装了必要的库:

bash 复制代码
pip install streamlit firebase-admin google-cloud-storage

新建一个 app.py,代码如下(包含数据库读写 + 读取 Storage 文件):

python 复制代码
import streamlit as st
import firebase_admin
from firebase_admin import credentials
from firebase_admin import firestore
from firebase_admin import storage  # 引入存储模块
import datetime

# ==========================================
# 0. 配置区域 (请修改这里!)
# ==========================================
# 你的 Bucket 名字 (不需要带 gs://)
TARGET_BUCKET_NAME = "your-bucket-name"
# 你想读取的文件名 (比如 123.txt)
TARGET_FILE_NAME = "your.txt" 

# ==========================================
# 1. 初始化 Firebase 连接
# ==========================================
# 检查是否已经初始化,防止 Streamlit 刷新页面报错
if not firebase_admin._apps:
    # 加载你的管理员密钥
    cred = credentials.Certificate("key.json")
    
    # 初始化 App
    firebase_admin.initialize_app(cred)

# 获取数据库客户端
db = firestore.client()

# ==========================================
# 2. 页面布局
# ==========================================
st.title("🔥 Firebase 全能演示")
st.caption("集成 Firestore 数据库 + Cloud Storage 文件读取")

# --- 分隔线 ---
st.divider()

# ==========================================
# 3. 功能 A:读取 Bucket 里的 TXT 文件
# ==========================================
st.header("📂 读取存储桶文件")
st.write(f"目标 Bucket: `{TARGET_BUCKET_NAME}` | 目标文件: `{TARGET_FILE_NAME}`")

if st.button("读取远程文件内容"):
    try:
        # 1. 获取 Bucket 对象
        # 注意:这里直接指定 bucket 名字,哪怕它不在 Firebase 项目里也能连(只要有权限)
        bucket = storage.bucket(TARGET_BUCKET_NAME)
        
        # 2. 获取文件对象 (Blob)
        blob = bucket.blob(TARGET_FILE_NAME)
        
        # 3. 下载并解码 (bytes -> string)
        # 如果文件很大,尽量不要用 download_as_string,这里仅做演示
        content = blob.download_as_string().decode("utf-8")
        
        # 4. 显示内容
        st.success("读取成功!")
        st.code(content, language="text") # 用代码框显示,好看一点
        
    except Exception as e:
        st.error("读取失败!请检查控制台错误信息。")
        st.warning(f"错误详情: {e}")
        st.info("提示:如果 Bucket 不是公开的,请确认 key.json 对应的服务账号在这个 Bucket 里有 'Storage Object Viewer' 权限。")

# --- 分隔线 ---
st.divider()

# ==========================================
# 4. 功能 B:留言板 (Firestore)
# ==========================================
st.header("💬 实时留言板")

# 侧边栏:写数据
with st.sidebar:
    st.header("📝 发送新消息")
    user_name = st.text_input("你的昵称", "Python大佬")
    msg_content = st.text_area("留言内容")
    
    if st.button("发送到数据库"):
        if msg_content:
            try:
                # 写入 Firestore
                db.collection("messages").add({
                    "content": msg_content,
                    "user": user_name,
                    "timestamp": datetime.datetime.now()
                })
                st.success("发送成功!")
            except Exception as e:
                st.error(f"写入失败: {e}")
        else:
            st.warning("写点东西再发呗")

# 主区域:读数据
if st.button("🔄 刷新留言列表"):
    st.rerun()

# 从 Firestore 读取数据 (按时间倒序)
try:
    docs = db.collection("messages").order_by("timestamp", direction=firestore.Query.DESCENDING).stream()
    
    msg_count = 0
    for doc in docs:
        msg_count += 1
        data = doc.to_dict()
        
        with st.chat_message("user"):
            st.write(f"**{data.get('user', '匿名')}** ({data.get('timestamp', '')})")
            st.markdown(data.get('content'))
            
    if msg_count == 0:
        st.write("还没有留言,快去侧边栏发一条!")
        
except Exception as e:
    st.error(f"连接数据库失败: {e}")

运行项目:

复制代码
streamlit run app.py

效果:你可以打开两个浏览器窗口,在一个窗口输入留言,另一个窗口会实时同步出现内容,非常丝滑。

4. 进阶思考:关于 CORS 和 权限

在上面的代码中,我增加了一个功能:读取 Cloud Storage Bucket 中的 .txt 文件。这里引出了两个非常有意思的问题。

问:为什么没有触发 CORS 跨域报错?

如果我们在前端 HTML/JS 里直接 fetch 一个 Bucket 的文件,通常会报 CORS 错误。但在 Python 代码里却没事,为什么?

:CORS (Cross-Origin Resource Sharing) 是浏览器的防御机制,用来防止恶意 JS 脚本跨域请求。

  • 本 Demo 的原理:请求是由 Python 后端(服务器端)发起的。
  • 服务器对服务器 (Server-to-Server) 的通信是不受 CORS 限制的。Python 相当于是一个代理,绕过了浏览器的限制。
问:如果 Bucket 是私有的 (Private),该怎么访问?

如果 Bucket 不是公开的,直接读取会报 403 Forbidden。解决方法是利用 IAM 权限管理。

我们初始化的 key.json 对应一个 Service Account (服务账号)。我们需要把这个"机器人"拉进 Bucket 的白名单里:

  1. 打开 key.json,找到 client_email 字段,复制那个 xxx@xxx.iam.gserviceaccount.com 的邮箱。
  2. 前往 Google Cloud Console (存储控制台)https://console.cloud.google.com/storage/browser
  3. 找到你的目标 Bucket,点击 权限 (Permissions)
  4. 点击 授予访问权限 (Grant Access)
  5. 新的主帐号:粘贴刚才的邮箱。
  6. 角色 :搜索并选择 Storage Object Viewer (存储对象查看者)
  7. 保存即可。

这样,你的 Python 脚本就拥有了合法的"查看权限",可以愉快地读取私有文件了!


有任何问题,欢迎随时私信交流 ~ 🚀


相关推荐
Sirius.z4 小时前
第R6周:LSTM实现糖尿病探索与预测
python
名字还没想好☜4 小时前
Python f-string 进阶:数字格式化、对齐填充、调试 = 号与嵌套表达式
开发语言·数据库·python·字符串格式化·f-string
ltl4 小时前
Serverless 数据库弹性理论:Neon 与 Aurora Serverless v2
数据库
·薯条大王4 小时前
经济实惠玩云服务器|一台云服务器多人共用,子账号配置教程
java·linux·运维·服务器·汇编·c++·python
互联网中的一颗神经元5 小时前
04 — 安全撤销:改错了怎么退回去
大数据·安全·elasticsearch
Dxy12393102165 小时前
Python 如何使用 MySQL 的事务
python·mysql
marvelyu9 小时前
每天10分钟学会OceanBase系列(Day 20):跨机房容灾实战——构建多数据中心高可用架构
java·大数据·数据库
ZCBUS实时计算9 小时前
金融证券实时数仓建设实践:轻量化实时计算平台落地,实现交易数据端到端秒级处理
大数据·数据库·数据仓库·金融·flink·dba·etl
智脑API9 小时前
Claude Code sandbox.failIfUnavailable 怎么用?沙箱启动失败、拒绝降级和 CI 安全
安全·ci/cd
zd2005729 小时前
海洋微生物数据库
数据库·宏基因组