You've already forked opc-backend
79 lines
2.6 KiB
Python
79 lines
2.6 KiB
Python
|
|
from minio import Minio
|
||
|
|
from django.conf import settings
|
||
|
|
import uuid
|
||
|
|
import os
|
||
|
|
import json
|
||
|
|
import logging
|
||
|
|
|
||
|
|
logger = logging.getLogger(__name__)
|
||
|
|
|
||
|
|
class MinioClient:
|
||
|
|
def __init__(self):
|
||
|
|
self._client = None
|
||
|
|
self.bucket_name = getattr(settings, 'MINIO_BUCKET_NAME', 'opc-assets')
|
||
|
|
self._initialized = False
|
||
|
|
|
||
|
|
@property
|
||
|
|
def client(self):
|
||
|
|
if self._client is None:
|
||
|
|
self._client = Minio(
|
||
|
|
endpoint=getattr(settings, 'MINIO_ENDPOINT', 'localhost:9000'),
|
||
|
|
access_key=getattr(settings, 'MINIO_ACCESS_KEY', 'minioadmin'),
|
||
|
|
secret_key=getattr(settings, 'MINIO_SECRET_KEY', 'minioadmin'),
|
||
|
|
secure=getattr(settings, 'MINIO_SECURE', False)
|
||
|
|
)
|
||
|
|
if not self._initialized:
|
||
|
|
try:
|
||
|
|
self._ensure_bucket()
|
||
|
|
self._initialized = True
|
||
|
|
except Exception as e:
|
||
|
|
logger.warning(f'MinIO bucket init failed (will retry on next call): {e}')
|
||
|
|
return self._client
|
||
|
|
|
||
|
|
def _ensure_bucket(self):
|
||
|
|
if not self._client.bucket_exists(self.bucket_name):
|
||
|
|
self._client.make_bucket(self.bucket_name)
|
||
|
|
|
||
|
|
# Always update policy to ensure public access
|
||
|
|
policy = {
|
||
|
|
"Version": "2012-10-17",
|
||
|
|
"Statement": [
|
||
|
|
{
|
||
|
|
"Effect": "Allow",
|
||
|
|
"Principal": {"AWS": ["*"]},
|
||
|
|
"Action": ["s3:GetBucketLocation", "s3:ListBucket"],
|
||
|
|
"Resource": [f"arn:aws:s3:::{self.bucket_name}"],
|
||
|
|
},
|
||
|
|
{
|
||
|
|
"Effect": "Allow",
|
||
|
|
"Principal": {"AWS": ["*"]},
|
||
|
|
"Action": ["s3:GetObject"],
|
||
|
|
"Resource": [f"arn:aws:s3:::{self.bucket_name}/*"],
|
||
|
|
},
|
||
|
|
],
|
||
|
|
}
|
||
|
|
self._client.set_bucket_policy(self.bucket_name, json.dumps(policy))
|
||
|
|
|
||
|
|
def upload_file(self, file_obj, folder='general'):
|
||
|
|
# Generate a unique name
|
||
|
|
ext = os.path.splitext(file_obj.name)[1]
|
||
|
|
file_name = f"{folder}/{uuid.uuid4()}{ext}"
|
||
|
|
|
||
|
|
# Upload (this will trigger lazy init of the client)
|
||
|
|
self.client.put_object(
|
||
|
|
self.bucket_name,
|
||
|
|
file_name,
|
||
|
|
file_obj,
|
||
|
|
length=file_obj.size,
|
||
|
|
content_type=file_obj.content_type
|
||
|
|
)
|
||
|
|
|
||
|
|
# Return the public URL
|
||
|
|
base_url = getattr(settings, 'MINIO_PUBLIC_URL', 'http://127.0.0.1:9000')
|
||
|
|
return f"{base_url}/{self.bucket_name}/{file_name}"
|
||
|
|
|
||
|
|
|
||
|
|
# Lazy singleton — does NOT connect at import time
|
||
|
|
minio_client = MinioClient()
|
||
|
|
|