Skip to content

Commit a0194b8

Browse files
committed
feat: 更新 MinIO 上传功能,支持指定存储桶并添加公共读取策略,修复文件上传bug
1 parent 42b7597 commit a0194b8

File tree

3 files changed

+52
-6
lines changed

3 files changed

+52
-6
lines changed

server/routers/auth_router.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -603,7 +603,7 @@ async def upload_user_avatar(
603603
file_extension = file.filename.split(".")[-1].lower() if file.filename and "." in file.filename else "jpg"
604604

605605
# 上传到MinIO
606-
avatar_url = upload_image_to_minio(file_content, file_extension)
606+
avatar_url = upload_image_to_minio("avatar", file_content, file_extension)
607607

608608
# 更新用户头像
609609
current_user.avatar = avatar_url

src/agents/chatbot/tools.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ async def text_to_img_qwen(text: str) -> str:
6060
response = requests.get(image_url)
6161
file_data = response.content
6262

63-
image_url = upload_image_to_minio(data=file_data, file_extension="jpg")
63+
image_url = upload_image_to_minio(bucket_name="generated-images", data=file_data, file_extension="jpg")
6464
logger.info(f"Image uploaded. URL: {image_url}")
6565
return image_url
6666

src/storage/minio/client.py

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
简化的 MinIO 对象存储操作
44
"""
55

6+
import json
67
import os
78
import uuid
89
from io import BytesIO
@@ -32,6 +33,8 @@ class MinIOClient:
3233
简化的 MinIO 客户端类
3334
"""
3435

36+
PUBLIC_READ_BUCKETS = {"generated-images", "avatar"}
37+
3538
def __init__(self):
3639
"""初始化 MinIO 客户端"""
3740
self.endpoint = os.getenv("MINIO_URI", "http://milvus-minio:9000")
@@ -41,7 +44,12 @@ def __init__(self):
4144

4245
# 设置公开访问端点
4346
if os.getenv("RUNNING_IN_DOCKER"):
44-
host_ip = os.getenv("HOST_IP", "localhost")
47+
host_ip = (os.getenv("HOST_IP") or "").strip()
48+
if not host_ip:
49+
host_ip = "localhost"
50+
if "://" in host_ip:
51+
host_ip = host_ip.split("://")[-1]
52+
host_ip = host_ip.rstrip("/")
4553
self.public_endpoint = f"{host_ip}:9000"
4654
else:
4755
self.public_endpoint = "localhost:9000"
@@ -62,14 +70,23 @@ def client(self) -> Minio:
6270
def ensure_bucket_exists(self, bucket_name: str) -> bool:
6371
"""确保存储桶存在"""
6472
try:
73+
created = False
6574
if not self.client.bucket_exists(bucket_name):
6675
self.client.make_bucket(bucket_name)
76+
created = True
6777
logger.info(f"存储桶 '{bucket_name}' 已创建")
68-
return True
78+
79+
self._ensure_public_read_access(bucket_name)
80+
81+
if created and bucket_name in self.PUBLIC_READ_BUCKETS:
82+
logger.info(f"存储桶 '{bucket_name}' 已配置为公开可读")
83+
6984
return True
7085
except S3Error as e:
7186
logger.error(f"存储桶 '{bucket_name}' 错误: {e}")
7287
raise StorageError(f"Error with bucket '{bucket_name}': {e}")
88+
except StorageError:
89+
raise
7390

7491
def upload_file(
7592
self, bucket_name: str, object_name: str, data: bytes, content_type: str = "application/octet-stream"
@@ -167,6 +184,35 @@ def file_exists(self, bucket_name: str, object_name: str) -> bool:
167184
return False
168185
raise StorageError(f"检查文件存在性失败: {e}")
169186

187+
def _ensure_public_read_access(self, bucket_name: str) -> None:
188+
"""设置存储桶策略,允许公开读取对象"""
189+
if bucket_name not in self.PUBLIC_READ_BUCKETS:
190+
return
191+
192+
policy = {
193+
"Version": "2012-10-17",
194+
"Statement": [
195+
{
196+
"Effect": "Allow",
197+
"Principal": {"AWS": ["*"]},
198+
"Action": ["s3:GetObject"],
199+
"Resource": [f"arn:aws:s3:::{bucket_name}/*"],
200+
},
201+
{
202+
"Effect": "Allow",
203+
"Principal": {"AWS": ["*"]},
204+
"Action": ["s3:ListBucket"],
205+
"Resource": [f"arn:aws:s3:::{bucket_name}"],
206+
},
207+
],
208+
}
209+
210+
try:
211+
self.client.set_bucket_policy(bucket_name, json.dumps(policy))
212+
except S3Error as e:
213+
logger.warning(f"设置存储桶 '{bucket_name}' 公共读取策略失败: {e}")
214+
raise StorageError(f"无法设置存储桶公共访问策略: {e}")
215+
170216

171217
# 全局客户端实例
172218
_default_client = None
@@ -180,7 +226,7 @@ def get_minio_client() -> MinIOClient:
180226
return _default_client
181227

182228

183-
def upload_image_to_minio(data: bytes, file_extension: str = "jpg") -> str:
229+
def upload_image_to_minio(bucket_name: str, data: bytes, file_extension: str = "jpg") -> str:
184230
"""
185231
上传图片到 MinIO(保持向后兼容)
186232
@@ -194,6 +240,6 @@ def upload_image_to_minio(data: bytes, file_extension: str = "jpg") -> str:
194240
client = get_minio_client()
195241
file_name = f"{uuid.uuid4()}.{file_extension}"
196242
result = client.upload_file(
197-
bucket_name="generated-images", object_name=file_name, data=data, content_type=f"image/{file_extension}"
243+
bucket_name=bucket_name, object_name=file_name, data=data, content_type=f"image/{file_extension}"
198244
)
199245
return result.url

0 commit comments

Comments
 (0)