Files
Pre_Seg_Server/backend/minio_client.py

128 lines
3.3 KiB
Python

"""MinIO client wrapper for object storage operations."""
import io
import logging
from typing import Optional
from minio import Minio
from minio.error import S3Error
from config import settings
logger = logging.getLogger(__name__)
BUCKET_NAME = "seg-media"
_minio_client: Optional[Minio] = None
def get_minio_client() -> Minio:
"""Return a singleton MinIO client instance."""
global _minio_client
if _minio_client is None:
_minio_client = Minio(
settings.minio_endpoint,
access_key=settings.minio_access_key,
secret_key=settings.minio_secret_key,
secure=settings.minio_secure,
)
return _minio_client
def ensure_bucket_exists() -> None:
"""Create the bucket if it does not already exist."""
client = get_minio_client()
try:
if not client.bucket_exists(BUCKET_NAME):
client.make_bucket(BUCKET_NAME)
logger.info("Created MinIO bucket: %s", BUCKET_NAME)
else:
logger.info("MinIO bucket %s already exists", BUCKET_NAME)
except S3Error as exc:
logger.error("MinIO bucket check/creation failed: %s", exc)
raise
def upload_file(
object_name: str,
data: bytes,
content_type: str = "application/octet-stream",
length: int = -1,
) -> str:
"""Upload bytes to MinIO and return the object name.
Args:
object_name: Destination path inside the bucket.
data: Raw bytes or a file-like object.
content_type: MIME type of the object.
length: Object size; -1 for unknown (uses chunked upload).
Returns:
The object name (same as input).
"""
client = get_minio_client()
if isinstance(data, bytes):
data = io.BytesIO(data)
length = len(data.getvalue())
try:
client.put_object(
BUCKET_NAME,
object_name,
data,
length=length,
content_type=content_type,
)
logger.info("Uploaded to MinIO: %s", object_name)
return object_name
except S3Error as exc:
logger.error("MinIO upload failed: %s", exc)
raise
from datetime import timedelta
def get_presigned_url(
object_name: str,
expires: int = 3600,
method: str = "GET",
) -> str:
"""Generate a presigned URL for an object.
Args:
object_name: Path inside the bucket.
expires: Expiration time in seconds (default 1 hour).
method: HTTP method (GET or PUT).
Returns:
Presigned URL string.
"""
client = get_minio_client()
try:
url = client.get_presigned_url(method, BUCKET_NAME, object_name, expires=timedelta(seconds=expires))
return url
except S3Error as exc:
logger.error("MinIO presigned URL failed: %s", exc)
raise
def download_file(object_name: str) -> bytes:
"""Download an object from MinIO and return its bytes.
Args:
object_name: Path inside the bucket.
Returns:
Raw bytes of the object.
"""
client = get_minio_client()
try:
response = client.get_object(BUCKET_NAME, object_name)
data = response.read()
response.close()
response.release_conn()
return data
except S3Error as exc:
logger.error("MinIO download failed: %s", exc)
raise