Supabase の Storage のオブジェクトの URL を JS で取得する2通りの方法
Supabase の Storage のオブジェクトの URL を取得する
Supabase の Storage のオブジェクトの URL を取得する方法は2通りある。
- Bucket が Public ではないとき、object を download してから URL を取得する
- Bucket が Public であるとき、
getPublicUrl
を使う
Bucket が Public ではないときの URL 取得方法
公式ドキュメント に書かれている Bucket のポリシーを適用する。
insert into storage.buckets (id, name) values ('avatars', 'avatars');
create policy "Public Access"
on storage.objects for select
using ( bucket_id = 'public' );
SQLを実行すると作成された Bucket は Public ではない。実際、avatars
Bucket には Public ラベルが付与されていない。
このとき、画像などのオブジェクトをこの Bucket にアップロードすると、発行される URL は signed url である。
例えば、filename.jpg
をavatars
Bucket にアップロードしたとすると、以下のような URL が発行される。
https://randomstring.supabase.in/storage/v1/object/sign/avatars/filename.jpg?token=long-random-string-token
このオブジェクトの URL を JS で取得する方法は以下の通り。
const { data, error } = await supabase.storage.from('avatars').download('filename.jpg')
if (data === null) return
const url = URL.createObjectURL(data)
data の型は Blob | null
。
この方法は Supabase の Next.js のサンプル に記述されている。
Bucket が Public のときのオブジェクトの URL 取得方法
まずは Public な Bucket を作成する。GUI でも可能だが、ここでは SQL の方法を紹介する。
insert into storage.buckets (id, name, public) values ('avatars', 'avatars', true);
Bucket が Public か否かは storage.buckets
テーブルのカラムを見ればわかる。このため、Bucket 作成時に Public フラグを true にしておく。
この SQL を実行すると、avatars
Bucket は Public になる。
この Bucket にfilename.jpg
をアップロードすると、以下のような URL が得られる。
https://randomstring.supabase.in/storage/v1/object/public/avatars/filename.jpg
これを JS で取得するコードは以下の通り。
const url = await supabase.storage.from('avatars').getPublicUrl('filename.jpg')
上記では Bucket にポリシーを付与していない。しかし、基本的には以下のようなポリシーを設定すると良いだろう。
create policy "Avatar images are publicly accessible."
on storage.objects for select using ( bucket_id = 'avatars' );
create policy "Logged-in user can upload an avatar."
on storage.objects for insert with check ( bucket_id = 'avatars' AND role() = 'authenticated' );
create policy "Users can update their own avatar."
on storage.objects for update with check ( bucket_id = 'avatars' AND uid() = owner );
create policy "Users can delete their own avatar."
on storage.objects for update with check ( bucket_id = 'avatars' AND uid() = owner );
これで、参照は誰でも可能、アップロードはログイン済みユーザー、更新、削除は所有者(アップロードした人)のみに制限できる。
共有ありがとうございます。
相談なのですが、
1. Bucket が Public ではないとき、object を download してから URL を取得する
だとURLに比べると表示スピードはかなり遅くなりそうな感覚なのですがいかがでしょう?
今supabaseのstorageを使うか、直接awsのS3にするか選定しており、
特定のアクセス権を持つユーザーだけが保存した画像を閲覧できるようにしたいと考えています。
supabaseのstorageを使うとなると、downloadするしかなさそうですよね。。