átlagos kiegészítséek jó sok
This commit is contained in:
@@ -1,31 +1,170 @@
|
||||
# /opt/docker/dev/service_finder/backend/app/services/storage_service.py
|
||||
import uuid
|
||||
import socket
|
||||
from io import BytesIO
|
||||
from datetime import timedelta
|
||||
from minio import Minio
|
||||
from minio.error import S3Error
|
||||
from app.core.config import settings
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class StorageService:
|
||||
# A klienst a beállításokból inicializáljuk
|
||||
client = Minio(
|
||||
settings.REDIS_URL.split("//")[1].split(":")[0], # Gyors fix a hostra vagy settings.MINIO_HOST
|
||||
access_key="minioadmin",
|
||||
secret_key="minioadmin",
|
||||
secure=False
|
||||
)
|
||||
"""MinIO S3 objektumtároló szolgáltatás."""
|
||||
|
||||
@classmethod
|
||||
def _resolve_endpoint(cls, endpoint: str) -> str:
|
||||
"""
|
||||
Resolve hostname to IP address if endpoint contains a hostname.
|
||||
This helps with MinIO 'invalid hostname' issues.
|
||||
"""
|
||||
if "://" in endpoint:
|
||||
# Remove protocol
|
||||
endpoint = endpoint.split("://")[1]
|
||||
|
||||
if ":" in endpoint:
|
||||
host, port = endpoint.split(":", 1)
|
||||
else:
|
||||
host, port = endpoint, "9000"
|
||||
|
||||
# Try to resolve hostname to IP
|
||||
try:
|
||||
ip = socket.gethostbyname(host)
|
||||
resolved_endpoint = f"{ip}:{port}"
|
||||
logger.debug(f"Resolved endpoint {endpoint} -> {resolved_endpoint}")
|
||||
return resolved_endpoint
|
||||
except socket.gaierror:
|
||||
logger.warning(f"Could not resolve hostname {host}, using original endpoint")
|
||||
return endpoint
|
||||
|
||||
# MinIO kliens inicializálása a konfigurációból
|
||||
@classmethod
|
||||
def _get_client(cls):
|
||||
"""Get MinIO client with resolved endpoint."""
|
||||
resolved_endpoint = cls._resolve_endpoint(settings.MINIO_ENDPOINT)
|
||||
return Minio(
|
||||
endpoint=resolved_endpoint,
|
||||
access_key=settings.MINIO_ACCESS_KEY,
|
||||
secret_key=settings.MINIO_SECRET_KEY,
|
||||
secure=settings.MINIO_SECURE,
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def _get_client_instance(cls):
|
||||
"""Get client instance (cached)."""
|
||||
if not hasattr(cls, '_client_instance'):
|
||||
cls._client_instance = cls._get_client()
|
||||
return cls._client_instance
|
||||
|
||||
# Client property
|
||||
@classmethod
|
||||
def client(cls):
|
||||
"""Get MinIO client instance."""
|
||||
return cls._get_client_instance()
|
||||
|
||||
@classmethod
|
||||
async def ensure_bucket_exists(cls, bucket_name: str) -> bool:
|
||||
"""
|
||||
Ellenőrzi, hogy a megadott vödör létezik-e, ha nem, létrehozza.
|
||||
|
||||
Args:
|
||||
bucket_name: A vödör neve
|
||||
|
||||
Returns:
|
||||
True ha a vödör létezik vagy sikeresen létrejött, False ha hiba történt.
|
||||
"""
|
||||
try:
|
||||
client = cls.client()
|
||||
if not client.bucket_exists(bucket_name):
|
||||
client.make_bucket(bucket_name)
|
||||
logger.info(f"Bucket '{bucket_name}' created.")
|
||||
else:
|
||||
logger.debug(f"Bucket '{bucket_name}' already exists.")
|
||||
return True
|
||||
except S3Error as e:
|
||||
logger.error(f"Error ensuring bucket '{bucket_name}': {e}")
|
||||
return False
|
||||
|
||||
@classmethod
|
||||
async def upload_image(
|
||||
cls,
|
||||
file_bytes: bytes,
|
||||
bucket_name: str,
|
||||
object_name: str,
|
||||
content_type: str = "application/octet-stream",
|
||||
) -> str:
|
||||
"""
|
||||
Feltölt egy fájlt a MinIO tárolóba.
|
||||
|
||||
Args:
|
||||
file_bytes: A fájl tartalma bájtokban
|
||||
bucket_name: Cél vödör neve
|
||||
object_name: Objektum neve (pl. 'images/photo.jpg')
|
||||
content_type: MIME típus (alapértelmezett: 'application/octet-stream')
|
||||
|
||||
Returns:
|
||||
Az objektum teljes elérési útja (bucket/object_name)
|
||||
|
||||
Raises:
|
||||
S3Error: Ha a feltöltés sikertelen
|
||||
"""
|
||||
await cls.ensure_bucket_exists(bucket_name)
|
||||
|
||||
# Feltöltés
|
||||
client = cls.client()
|
||||
client.put_object(
|
||||
bucket_name=bucket_name,
|
||||
object_name=object_name,
|
||||
data=BytesIO(file_bytes),
|
||||
length=len(file_bytes),
|
||||
content_type=content_type,
|
||||
)
|
||||
logger.info(f"Uploaded object '{object_name}' to bucket '{bucket_name}'.")
|
||||
return f"{bucket_name}/{object_name}"
|
||||
|
||||
@classmethod
|
||||
def get_presigned_url(
|
||||
cls,
|
||||
bucket_name: str,
|
||||
object_name: str,
|
||||
expires: timedelta = timedelta(hours=1),
|
||||
) -> str:
|
||||
"""
|
||||
Generál egy előjegyzett URL-t a fájl letöltéséhez.
|
||||
|
||||
Args:
|
||||
bucket_name: A vödör neve
|
||||
object_name: Az objektum neve
|
||||
expires: Az URL érvényességi ideje (alapértelmezett: 1 óra)
|
||||
|
||||
Returns:
|
||||
Az előjegyzett URL string
|
||||
"""
|
||||
try:
|
||||
client = cls.client()
|
||||
url = client.presigned_get_object(
|
||||
bucket_name=bucket_name,
|
||||
object_name=object_name,
|
||||
expires=int(expires.total_seconds()),
|
||||
)
|
||||
logger.debug(f"Generated presigned URL for '{bucket_name}/{object_name}'.")
|
||||
return url
|
||||
except S3Error as e:
|
||||
logger.error(f"Error generating presigned URL: {e}")
|
||||
raise
|
||||
|
||||
# Kompatibilitás a régi kóddal
|
||||
BUCKET_NAME = "vehicle-documents"
|
||||
|
||||
@classmethod
|
||||
async def upload_document(cls, file_bytes: bytes, file_name: str, folder: str) -> str:
|
||||
""" Fájl feltöltése S3/Minio tárhelyre. """
|
||||
if not cls.client.bucket_exists(cls.BUCKET_NAME):
|
||||
cls.client.make_bucket(cls.BUCKET_NAME)
|
||||
|
||||
unique_name = f"{folder}/{uuid.uuid4()}_{file_name}"
|
||||
|
||||
cls.client.put_object(
|
||||
cls.BUCKET_NAME,
|
||||
unique_name,
|
||||
BytesIO(file_bytes),
|
||||
len(file_bytes)
|
||||
)
|
||||
return f"{cls.BUCKET_NAME}/{unique_name}"
|
||||
"""Kompatibilitási metódus a régi kóddal."""
|
||||
object_name = f"{folder}/{uuid.uuid4()}_{file_name}"
|
||||
return await cls.upload_image(
|
||||
file_bytes=file_bytes,
|
||||
bucket_name=cls.BUCKET_NAME,
|
||||
object_name=object_name,
|
||||
content_type="application/octet-stream",
|
||||
)
|
||||
Reference in New Issue
Block a user