11import logging
2+ import os
23from contextlib import contextmanager
34from typing import Any , BinaryIO , Dict , List , Optional , Tuple
45
6+ import boto3
57import psycopg2
8+ from botocore .client import Config
9+ from botocore .exceptions import ClientError
610from sqlalchemy import create_engine
711from sqlalchemy .orm import class_mapper , sessionmaker
812
1923 POSTGRES_USER ,
2024)
2125from database .db_models import TableBase
22- from nexent .storage import create_storage_client_from_config , MinIOStorageConfig
23-
2426
2527logger = logging .getLogger ("database.client" )
2628
@@ -71,12 +73,6 @@ def clean_string_values(data: Dict[str, Any]) -> Dict[str, Any]:
7173
7274
7375class MinioClient :
74- """
75- MinIO client wrapper using storage SDK
76-
77- This class maintains backward compatibility with the existing MinioClient interface
78- while using the new storage SDK under the hood.
79- """
8076 _instance : Optional ['MinioClient' ] = None
8177
8278 def __new__ (cls ):
@@ -85,18 +81,39 @@ def __new__(cls):
8581 return cls ._instance
8682
8783 def __init__ (self ):
88- # Determine if endpoint uses HTTPS
89- secure = MINIO_ENDPOINT .startswith ('https://' ) if MINIO_ENDPOINT else True
90- # Initialize storage client using SDK factory
91- self .storage_config = MinIOStorageConfig (
92- endpoint = MINIO_ENDPOINT ,
93- access_key = MINIO_ACCESS_KEY ,
94- secret_key = MINIO_SECRET_KEY ,
95- region = MINIO_REGION ,
96- default_bucket = MINIO_DEFAULT_BUCKET ,
97- secure = secure
84+ self .endpoint = MINIO_ENDPOINT
85+ self .access_key = MINIO_ACCESS_KEY
86+ self .secret_key = MINIO_SECRET_KEY
87+ self .region = MINIO_REGION
88+ self .default_bucket = MINIO_DEFAULT_BUCKET
89+
90+ # Initialize S3 client with proxy settings
91+ self .client = boto3 .client (
92+ 's3' ,
93+ endpoint_url = self .endpoint ,
94+ aws_access_key_id = self .access_key ,
95+ aws_secret_access_key = self .secret_key ,
96+ region_name = self .region ,
97+ config = Config (
98+ signature_version = 's3v4' ,
99+ proxies = {
100+ 'http' : None ,
101+ 'https' : None
102+ }
103+ )
98104 )
99- self ._storage_client = create_storage_client_from_config (self .storage_config )
105+
106+ # Ensure default bucket exists
107+ self ._ensure_bucket_exists (self .default_bucket )
108+
109+ def _ensure_bucket_exists (self , bucket_name : str ) -> None :
110+ """Ensure bucket exists, create if it doesn't"""
111+ try :
112+ self .client .head_bucket (Bucket = bucket_name )
113+ except ClientError :
114+ # Bucket doesn't exist, create it
115+ self .client .create_bucket (Bucket = bucket_name )
116+ logger .info (f"Created bucket: { bucket_name } " )
100117
101118 def upload_file (
102119 self ,
@@ -115,7 +132,16 @@ def upload_file(
115132 Returns:
116133 Tuple[bool, str]: (Success status, File URL or error message)
117134 """
118- return self ._storage_client .upload_file (file_path , object_name , bucket )
135+ bucket = bucket or self .default_bucket
136+ if object_name is None :
137+ object_name = os .path .basename (file_path )
138+
139+ try :
140+ self .client .upload_file (file_path , bucket , object_name )
141+ file_url = f"/{ bucket } /{ object_name } "
142+ return True , file_url
143+ except Exception as e :
144+ return False , str (e )
119145
120146 def upload_fileobj (self , file_obj : BinaryIO , object_name : str , bucket : Optional [str ] = None ) -> Tuple [bool , str ]:
121147 """
@@ -129,7 +155,13 @@ def upload_fileobj(self, file_obj: BinaryIO, object_name: str, bucket: Optional[
129155 Returns:
130156 Tuple[bool, str]: (Success status, File URL or error message)
131157 """
132- return self ._storage_client .upload_fileobj (file_obj , object_name , bucket )
158+ bucket = bucket or self .default_bucket
159+ try :
160+ self .client .upload_fileobj (file_obj , bucket , object_name )
161+ file_url = f"/{ bucket } /{ object_name } "
162+ return True , file_url
163+ except Exception as e :
164+ return False , str (e )
133165
134166 def download_file (self , object_name : str , file_path : str , bucket : Optional [str ] = None ) -> Tuple [bool , str ]:
135167 """
@@ -143,7 +175,12 @@ def download_file(self, object_name: str, file_path: str, bucket: Optional[str]
143175 Returns:
144176 Tuple[bool, str]: (Success status, Success message or error message)
145177 """
146- return self ._storage_client .download_file (object_name , file_path , bucket )
178+ bucket = bucket or self .default_bucket
179+ try :
180+ self .client .download_file (bucket , object_name , file_path )
181+ return True , f"File downloaded successfully to { file_path } "
182+ except Exception as e :
183+ return False , str (e )
147184
148185 def get_file_url (self , object_name : str , bucket : Optional [str ] = None , expires : int = 3600 ) -> Tuple [bool , str ]:
149186 """
@@ -157,20 +194,23 @@ def get_file_url(self, object_name: str, bucket: Optional[str] = None, expires:
157194 Returns:
158195 Tuple[bool, str]: (Success status, Presigned URL or error message)
159196 """
160- return self ._storage_client .get_file_url (object_name , bucket , expires )
197+ bucket = bucket or self .default_bucket
198+ try :
199+ url = self .client .generate_presigned_url ('get_object' , Params = {'Bucket' : bucket , 'Key' : object_name },
200+ ExpiresIn = expires )
201+ return True , url
202+ except Exception as e :
203+ return False , str (e )
161204
162205 def get_file_size (self , object_name : str , bucket : Optional [str ] = None ) -> int :
163- """
164- Get file size in bytes
165-
166- Args:
167- object_name: Object name
168- bucket: Bucket name, if not specified use default bucket
169-
170- Returns:
171- int: File size in bytes, 0 if file not found or error
172- """
173- return self ._storage_client .get_file_size (object_name , bucket )
206+ bucket = bucket or self .default_bucket
207+ try :
208+ response = self .client .head_object (Bucket = bucket , Key = object_name )
209+ return int (response ['ContentLength' ])
210+ except ClientError as e :
211+ logger .error (
212+ f"Get file size by objectname({ object_name } ) failed: { e } " )
213+ return 0
174214
175215 def list_files (self , prefix : str = "" , bucket : Optional [str ] = None ) -> List [dict ]:
176216 """
@@ -183,7 +223,19 @@ def list_files(self, prefix: str = "", bucket: Optional[str] = None) -> List[dic
183223 Returns:
184224 List[dict]: List of file information
185225 """
186- return self ._storage_client .list_files (prefix , bucket )
226+ bucket = bucket or self .default_bucket
227+ try :
228+ response = self .client .list_objects_v2 (
229+ Bucket = bucket , Prefix = prefix )
230+ files = []
231+ if 'Contents' in response :
232+ for obj in response ['Contents' ]:
233+ files .append (
234+ {'key' : obj ['Key' ], 'size' : obj ['Size' ], 'last_modified' : obj ['LastModified' ]})
235+ return files
236+ except Exception as e :
237+ logger .error (f"Error listing files: { str (e )} " )
238+ return []
187239
188240 def delete_file (self , object_name : str , bucket : Optional [str ] = None ) -> Tuple [bool , str ]:
189241 """
@@ -196,7 +248,12 @@ def delete_file(self, object_name: str, bucket: Optional[str] = None) -> Tuple[b
196248 Returns:
197249 Tuple[bool, str]: (Success status, Success message or error message)
198250 """
199- return self ._storage_client .delete_file (object_name , bucket )
251+ bucket = bucket or self .default_bucket
252+ try :
253+ self .client .delete_object (Bucket = bucket , Key = object_name )
254+ return True , f"File { object_name } deleted successfully"
255+ except Exception as e :
256+ return False , str (e )
200257
201258 def get_file_stream (self , object_name : str , bucket : Optional [str ] = None ) -> Tuple [bool , Any ]:
202259 """
@@ -209,7 +266,12 @@ def get_file_stream(self, object_name: str, bucket: Optional[str] = None) -> Tup
209266 Returns:
210267 Tuple[bool, Any]: (Success status, File stream object or error message)
211268 """
212- return self ._storage_client .get_file_stream (object_name , bucket )
269+ bucket = bucket or self .default_bucket
270+ try :
271+ response = self .client .get_object (Bucket = bucket , Key = object_name )
272+ return True , response ['Body' ]
273+ except Exception as e :
274+ return False , str (e )
213275
214276
215277# Create global database and MinIO client instances
0 commit comments