108 lines
3.3 KiB
Python
108 lines
3.3 KiB
Python
"""MinIO storage service for file uploads."""
|
|
from minio import Minio
|
|
from minio.error import S3Error
|
|
from typing import BinaryIO
|
|
import os
|
|
from app.core.config import get_settings
|
|
|
|
|
|
class MinIOService:
|
|
"""MinIO storage service."""
|
|
|
|
def __init__(self):
|
|
"""Initialize MinIO client from settings."""
|
|
settings = get_settings()
|
|
|
|
self.client = Minio(
|
|
settings.minio_endpoint,
|
|
access_key=settings.minio_access_key,
|
|
secret_key=settings.minio_secret_key,
|
|
secure=settings.minio_secure,
|
|
)
|
|
self.bucket_name = settings.minio_bucket
|
|
self.public_url = settings.minio_public_url
|
|
self._ensure_bucket()
|
|
|
|
def _ensure_bucket(self):
|
|
"""Ensure bucket exists."""
|
|
try:
|
|
if not self.client.bucket_exists(self.bucket_name):
|
|
self.client.make_bucket(self.bucket_name)
|
|
# Set download policy for public access
|
|
policy = {
|
|
"Version": "2012-10-17",
|
|
"Statement": [
|
|
{
|
|
"Effect": "Allow",
|
|
"Principal": {"AWS": "*"},
|
|
"Action": ["s3:GetObject"],
|
|
"Resource": [f"arn:aws:s3:::{self.bucket_name}/*"]
|
|
}
|
|
]
|
|
}
|
|
import json
|
|
self.client.set_bucket_policy(self.bucket_name, json.dumps(policy))
|
|
except S3Error as e:
|
|
print(f"Error ensuring bucket: {e}")
|
|
|
|
def upload_file(
|
|
self,
|
|
file: BinaryIO,
|
|
storage_key: str,
|
|
content_type: str = "application/octet-stream",
|
|
) -> str:
|
|
"""
|
|
Upload file to MinIO.
|
|
|
|
Args:
|
|
file: File object to upload
|
|
storage_key: Storage path/key (e.g., "uploads/abc123/video.mp4")
|
|
content_type: MIME type of the file
|
|
|
|
Returns:
|
|
str: Public URL of uploaded file
|
|
"""
|
|
try:
|
|
# Get file size
|
|
file.seek(0, os.SEEK_END)
|
|
file_size = file.tell()
|
|
file.seek(0)
|
|
|
|
# Upload file
|
|
self.client.put_object(
|
|
self.bucket_name,
|
|
storage_key,
|
|
file,
|
|
file_size,
|
|
content_type=content_type,
|
|
)
|
|
|
|
# Return public URL
|
|
return f"{self.public_url}/{self.bucket_name}/{storage_key}"
|
|
|
|
except S3Error as e:
|
|
raise Exception(f"Failed to upload file: {e}")
|
|
|
|
def get_url(self, storage_key: str) -> str:
|
|
"""Get public URL for a storage key."""
|
|
return f"{self.public_url}/{self.bucket_name}/{storage_key}"
|
|
|
|
def delete_file(self, storage_key: str):
|
|
"""Delete file from MinIO."""
|
|
try:
|
|
self.client.remove_object(self.bucket_name, storage_key)
|
|
except S3Error as e:
|
|
print(f"Error deleting file: {e}")
|
|
|
|
|
|
# Singleton instance
|
|
_minio_service = None
|
|
|
|
|
|
def get_minio_service() -> MinIOService:
|
|
"""Get or create MinIO service instance."""
|
|
global _minio_service
|
|
if _minio_service is None:
|
|
_minio_service = MinIOService()
|
|
return _minio_service
|