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 脚本就拥有了合法的"查看权限",可以愉快地读取私有文件了!


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


相关推荐
小二·17 小时前
Python Web 全栈开发实战教程:基于 Flask 与 Layui 的待办事项系统
前端·python·flask
chipsense18 小时前
强电流环境下用霍尔电流传感器,安全性能有保障么?
安全·霍尔电流传感器
万物得其道者成18 小时前
用 Python + MySQL + Web 打造我的私有 Apple 设备监控面板
前端·python·mysql
安全渗透Hacker18 小时前
参数未校验导致的DOS(服务拒绝)问题典型场景
java·安全·web安全·网络安全·安全性测试
程序 代码狂人18 小时前
SQL-速查表:NULL 相关函数对比
数据库·sql
bigHead-18 小时前
Git合并操作详解:安全高效地合并远程分支
git·安全·elasticsearch
kaico201818 小时前
MYSQL的日志文件
数据库·mysql
pusheng202518 小时前
双气联防技术在下一代储能系统安全预警中的应用
前端·安全
oMcLin18 小时前
如何在AlmaLinux 9上优化MariaDB Galera Cluster,提升数据库集群的事务一致性与并发处理能力?
数据库·mariadb