33简化的 MinIO 对象存储操作
44"""
55
6+ import json
67import os
78import uuid
89from 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