first
This commit is contained in:
63
sop-back/app/services/storage.py
Normal file
63
sop-back/app/services/storage.py
Normal file
@@ -0,0 +1,63 @@
|
||||
import uuid
|
||||
import boto3
|
||||
from botocore.client import Config
|
||||
from botocore.exceptions import ClientError
|
||||
from app.core.config import settings
|
||||
|
||||
|
||||
def _client():
|
||||
return boto3.client(
|
||||
"s3",
|
||||
endpoint_url=settings.S3_ENDPOINT_URL,
|
||||
aws_access_key_id=settings.S3_ACCESS_KEY,
|
||||
aws_secret_access_key=settings.S3_SECRET_KEY,
|
||||
region_name=settings.S3_REGION,
|
||||
config=Config(signature_version="s3v4"),
|
||||
)
|
||||
|
||||
|
||||
def ensure_bucket() -> None:
|
||||
s3 = _client()
|
||||
try:
|
||||
s3.head_bucket(Bucket=settings.S3_BUCKET)
|
||||
except ClientError:
|
||||
s3.create_bucket(Bucket=settings.S3_BUCKET)
|
||||
# Make objects publicly readable so the frontend can <img src=...> directly.
|
||||
policy = (
|
||||
'{"Version":"2012-10-17","Statement":[{"Effect":"Allow","Principal":{"AWS":["*"]},'
|
||||
'"Action":["s3:GetObject"],"Resource":["arn:aws:s3:::'
|
||||
+ settings.S3_BUCKET
|
||||
+ '/*"]}]}'
|
||||
)
|
||||
try:
|
||||
s3.put_bucket_policy(Bucket=settings.S3_BUCKET, Policy=policy)
|
||||
except ClientError:
|
||||
pass
|
||||
|
||||
|
||||
def upload_image(file_bytes: bytes, filename: str, content_type: str) -> tuple[str, str]:
|
||||
"""Upload bytes to S3, return (object_key, public_url)."""
|
||||
ext = ""
|
||||
if "." in filename:
|
||||
ext = "." + filename.rsplit(".", 1)[-1].lower()
|
||||
key = f"characters/{uuid.uuid4().hex}{ext}"
|
||||
s3 = _client()
|
||||
s3.put_object(
|
||||
Bucket=settings.S3_BUCKET,
|
||||
Key=key,
|
||||
Body=file_bytes,
|
||||
ContentType=content_type or "application/octet-stream",
|
||||
)
|
||||
public_url = f"{settings.S3_PUBLIC_URL.rstrip('/')}/{settings.S3_BUCKET}/{key}"
|
||||
return key, public_url
|
||||
|
||||
|
||||
def delete_object_by_url(url: str) -> None:
|
||||
prefix = f"{settings.S3_PUBLIC_URL.rstrip('/')}/{settings.S3_BUCKET}/"
|
||||
if not url.startswith(prefix):
|
||||
return
|
||||
key = url[len(prefix):]
|
||||
try:
|
||||
_client().delete_object(Bucket=settings.S3_BUCKET, Key=key)
|
||||
except ClientError:
|
||||
pass
|
||||
Reference in New Issue
Block a user