文章目录
- (一)Supabase
- (二)Realtime(消息)
- (2.1)Python 消息订阅
- (2.2)JavaScript 消息订阅
- (三)Storage(存储)
- (3.1)Python 存储操作
- (3.2)JavaScript 存储操作
(一)Supabase
在《用 Next.js 和 Supabase 进行“全栈”开发的入门》中,我搭(抄)建(袭)了一个类似论坛雏形的东西。
后端用了Supabase,但例子中仅限于数据库CRUD(增删改查)的操作。
如果用Supabase只是Postgres用数据库,那么就称不上BaaS了吧😄
因为万恶的简称会重复,网上搜BaaS会出来:羊叫声,区块链即服务,蔚来汽车租电模式,绑定为服务……所以……
概念:
- 💡BaaS = Backend as a Service,就是一种云服务,旨在为移动和 Web 应用提供后端云服务,包括云端数据/文件存储、账户管理、消息推送等等……
打开Supabase的仪表板,除了已经用到的数据库和认证以外,还有3个主要内容:
- Realtime
- Storage
- Edge Functions
(二)Realtime(消息)
简单说Supabase的Realtime
就是实时的消息推送。
当我们把一张表的Realtime
选项开启后,这张表数据的增删改操作,都会产生消息,并且推送到每个订阅了这个频道消息的客户端上。
⚠️ 注意:
Realtime
是基于WebSocket
。不能保证每条消息都送到,所以你的应用如果有严格的要求,就不能完全依靠Realtime
的推送,比如也使用长轮询Long Polling
。
图)表开启Realtime:
图)设置RealTime涉及的操作。
调试时我们可以在Supabase仪表板中作为客户端,订阅一个Realtime
的频道。
实际使用时,我们需要用到Supabase社区项目来连接和使用消息订阅,如下。
(2.1)Python 消息订阅
见:🔗Supabase社区项目
from realtime.connection import SocketSUPABASE_ID = "你的ID"
API_KEY = "你的匿名Key或系统Key"def callback1(payload):print("Callback 1: ", payload)if __name__ == "__main__":URL = f"wss://{SUPABASE_ID}.supabase.co/realtime/v1/websocket?apikey={API_KEY}&vsn=1.0.0"s = Socket(URL)s.connect()channel_1 = s.set_channel("realtime:*")channel_1.join().on("UPDATE", callback1)s.listen()
(2.2)JavaScript 消息订阅
见:🔗Supabase社区项目
import { RealtimeClient } from '@supabase/realtime-js'const client = new RealtimeClient(REALTIME_URL, {params: {apikey: API_KEY},
})const channel = client.channel('test-channel', {})channel.subscribe((status, err) => {if (status === 'SUBSCRIBED') {console.log('Connected!')}if (status === 'CHANNEL_ERROR') {console.log(`There was an error subscribing to channel: ${err.message}`)}if (status === 'TIMED_OUT') {console.log('Realtime server did not respond in time.')}if (status === 'CLOSED') {console.log('Realtime channel was unexpectedly closed.')}
})
(三)Storage(存储)
简单说Supabase提供的文件存储是桶buckets
,可以当成一个盘符,一个挂载的设备。
在一个bucket
里面,可以创建目录和文件。
⚠️ 注意:公开的桶
public bucket
,仅表示它有一个可用于下载文件的公有 URL。
所有其他关于存储桶或文件的操作,都要求您满足该存储桶上的存储策略(权限)。
另请注意,您应该对所有其他操作使用正常路径,而不是包含“public”的公共 URL 路径。
怪不得找不到桶……
(3.1)Python 存储操作
见:🔗Supabase社区项目
初始化客户端
import os
from supabase import create_client, Clienturl: str = os.environ.get("SUPABASE_URL")
key: str = os.environ.get("SUPABASE_KEY")
supabase: Client = create_client(url, key)
下载文件
bucket_name: str = "photos"
data = supabase.storage.from_(bucket_name).download("photo1.png")
上传文件
bucket_name: str = "photos"
new_file = getUserFile()
data = supabase.storage.from_(bucket_name).upload("/user1/profile.png", new_file)
删除文件
bucket_name: str = "photos"
data = supabase.storage.from_(bucket_name).remove(["old_photo.png", "image5.jpg"])
列举全部文件
bucket_name: str = "charts"
data = supabase.storage.from_(bucket_name).list()
移动/重命名文件
bucket_name: str = "charts"
old_file_path: str = "generic/graph1.png"
new_file_path: str = "important/revenue.png"
data = supabase.storage.from_(bucket_name).move(old_file_path, new_file_path)
(3.2)JavaScript 存储操作
见:🔗Supabase项目
下载文件
const { data, error } = await supabase.storage.from('avatars').download('folder/avatar1.png')
上传文件
const avatarFile = event.target.files[0]
const { data, error } = await supabase.storage.from('avatars').upload('public/avatar1.png', avatarFile, {cacheControl: '3600',upsert: false})
删除文件
const { data, error } = await supabase.storage.from('avatars').remove(['folder/avatar1.png'])
列举全部文件
const { data, error } = await supabase.storage.from('avatars').list('folder', {limit: 100,offset: 0,sortBy: { column: 'name', order: 'asc' },})
获得文件公开URL
const { data } = supabase.storage.from('public-bucket').getPublicUrl('folder/avatar1.png')