forked from langgenius/dify
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add supabase object storage (langgenius#9229)
- Loading branch information
Showing
8 changed files
with
318 additions
and
105 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
from typing import Optional | ||
|
||
from pydantic import BaseModel, Field | ||
|
||
|
||
class SupabaseStorageConfig(BaseModel): | ||
""" | ||
Configuration settings for Supabase Object Storage Service | ||
""" | ||
|
||
SUPABASE_BUCKET_NAME: Optional[str] = Field( | ||
description="Name of the Supabase bucket to store and retrieve objects (e.g., 'dify-bucket')", | ||
default=None, | ||
) | ||
|
||
SUPABASE_API_KEY: Optional[str] = Field( | ||
description="API KEY for authenticating with Supabase", | ||
default=None, | ||
) | ||
|
||
SUPABASE_URL: Optional[str] = Field( | ||
description="URL of the Supabase", | ||
default=None, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
import io | ||
from collections.abc import Generator | ||
from pathlib import Path | ||
|
||
from flask import Flask | ||
from supabase import Client | ||
|
||
from extensions.storage.base_storage import BaseStorage | ||
|
||
|
||
class SupabaseStorage(BaseStorage): | ||
"""Implementation for supabase obs storage.""" | ||
|
||
def __init__(self, app: Flask): | ||
super().__init__(app) | ||
app_config = self.app.config | ||
self.bucket_name = app_config.get("SUPABASE_BUCKET_NAME") | ||
self.client = Client( | ||
supabase_url=app_config.get("SUPABASE_URL"), supabase_key=app_config.get("SUPABASE_API_KEY") | ||
) | ||
self.create_bucket( | ||
id=app_config.get("SUPABASE_BUCKET_NAME"), bucket_name=app_config.get("SUPABASE_BUCKET_NAME") | ||
) | ||
|
||
def create_bucket(self, id, bucket_name): | ||
if not self.bucket_exists(): | ||
self.client.storage.create_bucket(id=id, name=bucket_name) | ||
|
||
def save(self, filename, data): | ||
self.client.storage.from_(self.bucket_name).upload(filename, data) | ||
|
||
def load_once(self, filename: str) -> bytes: | ||
content = self.client.storage.from_(self.bucket_name).download(filename) | ||
return content | ||
|
||
def load_stream(self, filename: str) -> Generator: | ||
def generate(filename: str = filename) -> Generator: | ||
result = self.client.storage.from_(self.bucket_name).download(filename) | ||
byte_stream = io.BytesIO(result) | ||
while chunk := byte_stream.read(4096): # Read in chunks of 4KB | ||
yield chunk | ||
|
||
return generate() | ||
|
||
def download(self, filename, target_filepath): | ||
result = self.client.storage.from_(self.bucket_name).download(filename) | ||
Path(result).write_bytes(result) | ||
|
||
def exists(self, filename): | ||
result = self.client.storage.from_(self.bucket_name).list(filename) | ||
if result.count() > 0: | ||
return True | ||
return False | ||
|
||
def delete(self, filename): | ||
self.client.storage.from_(self.bucket_name).remove(filename) | ||
|
||
def bucket_exists(self): | ||
buckets = self.client.storage.list_buckets() | ||
return any(bucket.name == self.bucket_name for bucket in buckets) |
Oops, something went wrong.