102 lines
3.1 KiB
Python
102 lines
3.1 KiB
Python
import os
|
|
from io import BytesIO
|
|
from typing import Any
|
|
|
|
STORAGE_BASE = os.getenv("LOCAL_STORAGE_PATH", "./data/files")
|
|
MINIO_ENDPOINT = os.getenv("MINIO_ENDPOINT", "localhost:9000")
|
|
MINIO_ACCESS_KEY = os.getenv("MINIO_ACCESS_KEY", "minioadmin")
|
|
MINIO_SECRET_KEY = os.getenv("MINIO_SECRET_KEY", "minioadmin")
|
|
MINIO_SECURE = os.getenv("MINIO_SECURE", "false").lower() == "true"
|
|
|
|
|
|
def _local_path(bucket: str, file_path: str) -> str:
|
|
return os.path.join(STORAGE_BASE, bucket, file_path)
|
|
|
|
|
|
def _save_local(bucket: str, file_path: str, content: bytes) -> str:
|
|
full_path = _local_path(bucket, file_path)
|
|
os.makedirs(os.path.dirname(full_path), exist_ok=True)
|
|
with open(full_path, "wb") as f:
|
|
f.write(content)
|
|
return full_path
|
|
|
|
|
|
def _read_local(bucket: str, file_path: str) -> bytes:
|
|
with open(_local_path(bucket, file_path), "rb") as f:
|
|
return f.read()
|
|
|
|
|
|
def get_minio_client() -> Any:
|
|
from minio import Minio
|
|
|
|
return Minio(
|
|
MINIO_ENDPOINT,
|
|
access_key=MINIO_ACCESS_KEY,
|
|
secret_key=MINIO_SECRET_KEY,
|
|
secure=MINIO_SECURE,
|
|
)
|
|
|
|
|
|
def ensure_bucket(bucket_name: str) -> bool:
|
|
"""确保 bucket 存在;MinIO 不可用时返回 False 表示使用本地降级。"""
|
|
try:
|
|
client = get_minio_client()
|
|
if not client.bucket_exists(bucket_name):
|
|
client.make_bucket(bucket_name)
|
|
return True
|
|
except Exception:
|
|
return False
|
|
|
|
|
|
def upload_file(bucket: str, file_path: str, content: bytes) -> str:
|
|
"""上传文件到 MinIO;连接失败时降级保存到本地文件系统。"""
|
|
if ensure_bucket(bucket):
|
|
try:
|
|
client = get_minio_client()
|
|
client.put_object(
|
|
bucket,
|
|
file_path,
|
|
BytesIO(content),
|
|
length=len(content),
|
|
content_type="application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
)
|
|
return f"minio://{bucket}/{file_path}"
|
|
except Exception:
|
|
pass
|
|
|
|
return _save_local(bucket, file_path, content)
|
|
|
|
|
|
def download_file(bucket: str, file_path: str) -> bytes:
|
|
"""从 MinIO 下载文件;读取失败时尝试本地降级路径。"""
|
|
if ensure_bucket(bucket):
|
|
try:
|
|
client = get_minio_client()
|
|
response = client.get_object(bucket, file_path)
|
|
try:
|
|
return response.read()
|
|
finally:
|
|
response.close()
|
|
response.release_conn()
|
|
except Exception:
|
|
pass
|
|
|
|
return _read_local(bucket, file_path)
|
|
|
|
|
|
def save_file(content: bytes, file_path: str) -> str:
|
|
"""兼容旧调用:保存到默认 templates bucket。"""
|
|
return upload_file("templates", file_path, content)
|
|
|
|
|
|
def read_file(file_path: str) -> bytes:
|
|
"""兼容旧调用:从默认 templates bucket 读取。"""
|
|
return download_file("templates", file_path)
|
|
|
|
|
|
def delete_file(file_path: str):
|
|
"""删除本地降级文件。MinIO 对象删除后续按接口需要再补充。"""
|
|
full_path = _local_path("templates", file_path)
|
|
if os.path.exists(full_path):
|
|
os.remove(full_path)
|