Firebase Storage 使用介绍
之前使用 Firebase 还有 streamlit 创建了个个人项目,想用其中的对象存储功能,翻了翻 Firebase 的 Cloud Storage 文档,没有 Python 的介绍。
不过好在文档中提到 Storage 基于 Google Cloud Storage,可以通过 Google Cloud Storage API 执行服务器端处理,遂研究了一下 Firebase 中 Storage 如何使用 Python 在服务器端进行操作。
Cloud Storage for Firebase 将您的文件存储在某个 Google Cloud Storage 存储桶中
基本配置
安装依赖库
pip install --upgrade google-cloud-storage
配置服务密钥
Firebase 项目的基本配置阶段,会生成一个服务密钥(json 格式的文件)用于验证,这里不过多介绍。
Storage 部分可以看到 Firebase 项目对应的存储桶位置。需要注意,我们使用 Google Cloud Storage API 进行操作,但是上面获得的服务密钥是没有创建 bucket 的权限的,只能对于这个项目 bucket 进行管理!
获取到 bucket 名称后,可以用下面简单的代码进行验证:
from google.cloud import storage
key_dict = XXX
storage_client = storage.Client.from_service_account_info(key_dict)
list(storage_client.list_buckets())
storage_client.bucket("<project-name>.appspot.com").blob(
"hello.txt"
).upload_from_string("Hello, World! ")
一些常用操作
因为不涉及 bucket 的操作,主要参考 Cloud Storage 中介绍的上传和下载方法进行实现。
bucket = storage_client.bucket("<project-name>.appspot.com")
关于文件命名规则
如果您在存储桶 your-bucket 中创建名为 folder1/file.txt 的对象,则该对象的路径为 your-bucket/folder1/file.txt,且 Cloud Storage 未在其中存储名为 folder1 的文件夹。从 Cloud Storage 的角度来看,字符串 folder1/ 是该对象的名称的一部分。但是,由于该对象的名称中包含 /,因此某些工具会实现文件夹的外观。
下载
# download
blob = bucket.blob("hello.txt")
contents = blob.download_as_string() # 下载到内存
blob.download_to_filename("hello_local.txt") # 下载到文件
上传
blob = bucket.blob("hello.txt")
# Optional: set a generation-match precondition to avoid potential race conditions and data corruptions.
# The request to upload is aborted if the object's generation number does not match your precondition.
# 目标对象还不存在时,设置 if_generation_match 为 0.
# 目标对象已存在于 bucket 时, 设置为它的 generation number.
precondition = 0 # 假定目标不存在
blob.upload_from_filename("hello_local.txt", if_generation_match=precondition)
blob.upload_from_string("Hello world!")
对象存在 generation
还有 metageneration
属性,具体可参见这里,相当于文件的 id,每次更新都会刷新。上传时,通过额外的选项 if_generation_match
进行指定,可以避免冲突的发生(例如已经上传成功了,又上传了一遍)。
查看 blob: 列出对象,查看对象元数据
列出对象 | Cloud Storage | Google Cloud
for blob in bucket.list_blobs():
print(blob.name)
for blob in bucket.list_blobs(prefix="test"):
print(blob.name)
查看和修改对象元数据 | Cloud Storage | Google Cloud
metageneration_match_precondition = blob.metageneration
metadata = {'color': 'Red', 'name': 'Test'}
blob.metadata = metadata
blob.patch(if_metageneration_match=metageneration_match_precondition)
删除对象
blob.reload() # Fetch blob metadata to use in generation_match_precondition.
generation_match_precondition = blob.generation
blob.delete(if_generation_match=generation_match_precondition)