fiuai-s3 0.3.9__py3-none-any.whl → 0.4.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of fiuai-s3 might be problematic. Click here for more details.

fiuai_s3/__init__.py CHANGED
@@ -8,5 +8,5 @@
8
8
  from .object_storage import ObjectStorage, ObjectStorageFactory, StorageConfig
9
9
  from .type import DocFileObject, DocSourceFrom, DocFileType
10
10
 
11
- __version__ = "0.3.9"
11
+ __version__ = "0.4.1"
12
12
  __all__ = ["ObjectStorage", "ObjectStorageFactory", "StorageConfig", "DocFileObject", "DocSourceFrom", "DocFileType"]
@@ -149,4 +149,107 @@ class AliCloudStorage(ObjectStorage):
149
149
  return files
150
150
  except Exception as e:
151
151
  logger.error(f"列出单据文件失败: {str(e)}")
152
- return []
152
+ return []
153
+
154
+ def generate_presigned_url(self, object_key: str, method: str = "GET", expires_in: int = 3600,
155
+ response_headers: Optional[Dict[str, str]] = None,
156
+ auth_tenant_id: Optional[str] = None,
157
+ auth_company_id: Optional[str] = None,
158
+ doc_id: Optional[str] = None) -> Optional[str]:
159
+ """
160
+ 生成预签名URL
161
+
162
+ Args:
163
+ object_key: 对象存储中的key
164
+ method: HTTP方法,支持 GET、PUT、POST、DELETE
165
+ expires_in: 过期时间(秒),默认3600秒(1小时)
166
+ response_headers: 响应头设置
167
+ auth_tenant_id: 租户ID(可选,若不传则用实例属性)
168
+ auth_company_id: 公司ID(可选,若不传则用实例属性)
169
+ doc_id: 单据ID(可选,若不传则用实例属性)
170
+
171
+ Returns:
172
+ Optional[str]: 预签名URL,失败时返回None
173
+ """
174
+ try:
175
+ # 验证参数
176
+ if not object_key:
177
+ raise ValueError("object_key 不能为空")
178
+
179
+ if method.upper() not in ["GET", "PUT", "POST", "DELETE"]:
180
+ raise ValueError(f"不支持的HTTP方法: {method}")
181
+
182
+ if expires_in <= 0 or expires_in > 604800: # 最大7天
183
+ raise ValueError("过期时间必须在1秒到604800秒(7天)之间")
184
+
185
+ # 生成预签名URL
186
+ from datetime import datetime, timedelta
187
+
188
+ if method.upper() == "GET":
189
+ url = self.bucket.sign_url(
190
+ method='GET',
191
+ key=object_key,
192
+ expires=expires_in,
193
+ headers=response_headers
194
+ )
195
+ elif method.upper() == "PUT":
196
+ url = self.bucket.sign_url(
197
+ method='PUT',
198
+ key=object_key,
199
+ expires=expires_in
200
+ )
201
+ elif method.upper() == "POST":
202
+ url = self.bucket.sign_url(
203
+ method='POST',
204
+ key=object_key,
205
+ expires=expires_in
206
+ )
207
+ elif method.upper() == "DELETE":
208
+ url = self.bucket.sign_url(
209
+ method='DELETE',
210
+ key=object_key,
211
+ expires=expires_in
212
+ )
213
+
214
+ logger.info(f"生成预签名URL成功: {object_key}, method: {method}")
215
+ return url
216
+
217
+ except Exception as e:
218
+ logger.error(f"生成预签名URL失败: {str(e)}")
219
+ return None
220
+
221
+ def generate_presigned_doc_url(self, filename: str, method: str = "GET", expires_in: int = 3600,
222
+ response_headers: Optional[Dict[str, str]] = None,
223
+ auth_tenant_id: Optional[str] = None,
224
+ auth_company_id: Optional[str] = None,
225
+ doc_id: Optional[str] = None) -> Optional[str]:
226
+ """
227
+ 生成单据文件的预签名URL
228
+
229
+ Args:
230
+ filename: 文件名
231
+ method: HTTP方法,支持 GET、PUT、POST、DELETE
232
+ expires_in: 过期时间(秒),默认3600秒(1小时)
233
+ response_headers: 响应头设置
234
+ auth_tenant_id: 租户ID(可选,若不传则用实例属性)
235
+ auth_company_id: 公司ID(可选,若不传则用实例属性)
236
+ doc_id: 单据ID(可选,若不传则用实例属性)
237
+
238
+ Returns:
239
+ Optional[str]: 预签名URL,失败时返回None
240
+ """
241
+ try:
242
+ # 构建单据文件路径
243
+ object_key = self._build_doc_path(filename, auth_tenant_id, auth_company_id, doc_id)
244
+
245
+ # 调用通用预签名URL生成方法
246
+ return self.generate_presigned_url(
247
+ object_key=object_key,
248
+ method=method,
249
+ expires_in=expires_in,
250
+ response_headers=response_headers
251
+ )
252
+
253
+ except Exception as e:
254
+ logger.error(f"生成单据文件预签名URL失败: {str(e)}")
255
+ return None
@@ -12,7 +12,7 @@ from minio import Minio
12
12
  from minio.error import S3Error
13
13
  from minio.commonconfig import Tags
14
14
  from ..object_storage import ObjectStorage, StorageConfig
15
- from ..type import DocFileObject, DocFileType, DocSourceFrom
15
+ from ..type import DocFileObject
16
16
 
17
17
  logger = logging.getLogger(__name__)
18
18
 
@@ -186,8 +186,6 @@ class MinioStorage(ObjectStorage):
186
186
  def upload_doc_file(self,
187
187
  filename: str,
188
188
  data: bytes,
189
- doc_source_from: Optional[DocSourceFrom] = None,
190
- doc_file_type: Optional[DocFileType] = None,
191
189
  tags: Optional[Dict[str, str]] = None,
192
190
  auth_tenant_id: Optional[str] = None,
193
191
  auth_company_id: Optional[str] = None,
@@ -199,13 +197,9 @@ class MinioStorage(ObjectStorage):
199
197
  object_key = self._build_doc_path(filename, auth_tenant_id, auth_company_id, doc_id)
200
198
  # 将tags转换为Tags对象
201
199
  tags_obj = Tags()
202
- for k, v in tags.items():
203
- tags_obj[k] = v
204
-
205
- doc_source_from = doc_source_from if doc_source_from else DocSourceFrom.OTHER
206
- doc_file_type = doc_file_type if doc_file_type else DocFileType.OTHER
207
- tags_obj["doc_source_from"] = doc_source_from.value
208
- tags_obj["doc_file_type"] = doc_file_type.value
200
+ if tags:
201
+ for k, v in tags.items():
202
+ tags_obj[k] = v
209
203
 
210
204
  self.client.put_object(
211
205
  bucket_name=self.bucket_name,
@@ -263,4 +257,110 @@ class MinioStorage(ObjectStorage):
263
257
  return files
264
258
  except S3Error as e:
265
259
  logger.error(f"list doc files failed: {str(e)}")
266
- return []
260
+ return []
261
+
262
+ def generate_presigned_url(self, object_key: str, method: str = "GET", expires_in: int = 3600,
263
+ response_headers: Optional[Dict[str, str]] = None,
264
+ auth_tenant_id: Optional[str] = None,
265
+ auth_company_id: Optional[str] = None,
266
+ doc_id: Optional[str] = None) -> Optional[str]:
267
+ """
268
+ 生成预签名URL
269
+
270
+ Args:
271
+ object_key: 对象存储中的key
272
+ method: HTTP方法,支持 GET、PUT、POST、DELETE
273
+ expires_in: 过期时间(秒),默认3600秒(1小时)
274
+ response_headers: 响应头设置
275
+ auth_tenant_id: 租户ID(可选,若不传则用实例属性)
276
+ auth_company_id: 公司ID(可选,若不传则用实例属性)
277
+ doc_id: 单据ID(可选,若不传则用实例属性)
278
+
279
+ Returns:
280
+ Optional[str]: 预签名URL,失败时返回None
281
+ """
282
+ try:
283
+ # 验证参数
284
+ if not object_key:
285
+ raise ValueError("object_key 不能为空")
286
+
287
+ if method.upper() not in ["GET", "PUT", "POST", "DELETE"]:
288
+ raise ValueError(f"不支持的HTTP方法: {method}")
289
+
290
+ if expires_in <= 0 or expires_in > 604800: # 最大7天
291
+ raise ValueError("过期时间必须在1秒到604800秒(7天)之间")
292
+
293
+ # 生成预签名URL
294
+ from datetime import timedelta
295
+
296
+ if method.upper() == "GET":
297
+ url = self.client.presigned_get_object(
298
+ bucket_name=self.bucket_name,
299
+ object_name=object_key,
300
+ expires=timedelta(seconds=expires_in),
301
+ response_headers=response_headers
302
+ )
303
+ elif method.upper() == "PUT":
304
+ url = self.client.presigned_put_object(
305
+ bucket_name=self.bucket_name,
306
+ object_name=object_key,
307
+ expires=timedelta(seconds=expires_in)
308
+ )
309
+ elif method.upper() == "POST":
310
+ url = self.client.presigned_post_policy(
311
+ bucket_name=self.bucket_name,
312
+ object_name=object_key,
313
+ expires=timedelta(seconds=expires_in)
314
+ )
315
+ elif method.upper() == "DELETE":
316
+ url = self.client.presigned_delete_object(
317
+ bucket_name=self.bucket_name,
318
+ object_name=object_key,
319
+ expires=timedelta(seconds=expires_in)
320
+ )
321
+
322
+ logger.info(f"生成预签名URL成功: {object_key}, method: {method}")
323
+ return url
324
+
325
+ except S3Error as e:
326
+ logger.error(f"生成预签名URL失败: {str(e)}")
327
+ return None
328
+ except Exception as e:
329
+ logger.error(f"生成预签名URL异常: {str(e)}")
330
+ return None
331
+
332
+ def generate_presigned_doc_url(self, filename: str, method: str = "GET", expires_in: int = 3600,
333
+ response_headers: Optional[Dict[str, str]] = None,
334
+ auth_tenant_id: Optional[str] = None,
335
+ auth_company_id: Optional[str] = None,
336
+ doc_id: Optional[str] = None) -> Optional[str]:
337
+ """
338
+ 生成单据文件的预签名URL
339
+
340
+ Args:
341
+ filename: 文件名
342
+ method: HTTP方法,支持 GET、PUT、POST、DELETE
343
+ expires_in: 过期时间(秒),默认3600秒(1小时)
344
+ response_headers: 响应头设置
345
+ auth_tenant_id: 租户ID(可选,若不传则用实例属性)
346
+ auth_company_id: 公司ID(可选,若不传则用实例属性)
347
+ doc_id: 单据ID(可选,若不传则用实例属性)
348
+
349
+ Returns:
350
+ Optional[str]: 预签名URL,失败时返回None
351
+ """
352
+ try:
353
+ # 构建单据文件路径
354
+ object_key = self._build_doc_path(filename, auth_tenant_id, auth_company_id, doc_id)
355
+
356
+ # 调用通用预签名URL生成方法
357
+ return self.generate_presigned_url(
358
+ object_key=object_key,
359
+ method=method,
360
+ expires_in=expires_in,
361
+ response_headers=response_headers
362
+ )
363
+
364
+ except Exception as e:
365
+ logger.error(f"生成单据文件预签名URL失败: {str(e)}")
366
+ return None
@@ -120,8 +120,6 @@ class ObjectStorage(ABC):
120
120
  def upload_doc_file(self,
121
121
  filename: str,
122
122
  data: bytes,
123
- doc_source_from: Optional[DocSourceFrom] = None,
124
- doc_file_type: Optional[DocFileType] = None,
125
123
  tags: Optional[Dict[str, str]] = None,
126
124
  auth_tenant_id: Optional[str] = None, auth_company_id: Optional[str] = None, doc_id: Optional[str] = None) -> bool:
127
125
  """
@@ -165,6 +163,52 @@ class ObjectStorage(ABC):
165
163
  """
166
164
  pass
167
165
 
166
+ @abstractmethod
167
+ def generate_presigned_url(self, object_key: str, method: str = "GET", expires_in: int = 3600,
168
+ response_headers: Optional[Dict[str, str]] = None,
169
+ auth_tenant_id: Optional[str] = None,
170
+ auth_company_id: Optional[str] = None,
171
+ doc_id: Optional[str] = None) -> Optional[str]:
172
+ """
173
+ 生成预签名URL
174
+
175
+ Args:
176
+ object_key: 对象存储中的key,如果为空则使用单据路径
177
+ method: HTTP方法,支持 GET、PUT、POST、DELETE
178
+ expires_in: 过期时间(秒),默认3600秒(1小时)
179
+ response_headers: 响应头设置
180
+ auth_tenant_id: 租户ID(可选,若不传则用实例属性)
181
+ auth_company_id: 公司ID(可选,若不传则用实例属性)
182
+ doc_id: 单据ID(可选,若不传则用实例属性)
183
+
184
+ Returns:
185
+ Optional[str]: 预签名URL,失败时返回None
186
+ """
187
+ pass
188
+
189
+ @abstractmethod
190
+ def generate_presigned_doc_url(self, filename: str, method: str = "GET", expires_in: int = 3600,
191
+ response_headers: Optional[Dict[str, str]] = None,
192
+ auth_tenant_id: Optional[str] = None,
193
+ auth_company_id: Optional[str] = None,
194
+ doc_id: Optional[str] = None) -> Optional[str]:
195
+ """
196
+ 生成单据文件的预签名URL
197
+
198
+ Args:
199
+ filename: 文件名
200
+ method: HTTP方法,支持 GET、PUT、POST、DELETE
201
+ expires_in: 过期时间(秒),默认3600秒(1小时)
202
+ response_headers: 响应头设置
203
+ auth_tenant_id: 租户ID(可选,若不传则用实例属性)
204
+ auth_company_id: 公司ID(可选,若不传则用实例属性)
205
+ doc_id: 单据ID(可选,若不传则用实例属性)
206
+
207
+ Returns:
208
+ Optional[str]: 预签名URL,失败时返回None
209
+ """
210
+ pass
211
+
168
212
  class ObjectStorageFactory:
169
213
  """对象存储工厂类"""
170
214
 
@@ -255,6 +299,68 @@ class ObjectStorageFactory:
255
299
  return MinioStorage(config, auth_tenant_id, auth_company_id, doc_id)
256
300
  else:
257
301
  raise ValueError(f"不支持的存储提供商: {provider}")
302
+
303
+ @classmethod
304
+ def generate_presigned_url(cls, object_key: str, method: str = "GET", expires_in: int = 3600,
305
+ response_headers: Optional[Dict[str, str]] = None,
306
+ auth_tenant_id: Optional[str] = None,
307
+ auth_company_id: Optional[str] = None,
308
+ doc_id: Optional[str] = None) -> Optional[str]:
309
+ """通过工厂类生成预签名URL
310
+
311
+ Args:
312
+ object_key: 对象存储中的key
313
+ method: HTTP方法,支持 GET、PUT、POST、DELETE
314
+ expires_in: 过期时间(秒),默认3600秒(1小时)
315
+ response_headers: 响应头设置
316
+ auth_tenant_id: 租户ID(可选)
317
+ auth_company_id: 公司ID(可选)
318
+ doc_id: 单据ID(可选)
319
+
320
+ Returns:
321
+ Optional[str]: 预签名URL,失败时返回None
322
+ """
323
+ storage = cls.get_instance()
324
+ return storage.generate_presigned_url(
325
+ object_key=object_key,
326
+ method=method,
327
+ expires_in=expires_in,
328
+ response_headers=response_headers,
329
+ auth_tenant_id=auth_tenant_id,
330
+ auth_company_id=auth_company_id,
331
+ doc_id=doc_id
332
+ )
333
+
334
+ @classmethod
335
+ def generate_presigned_doc_url(cls, filename: str, method: str = "GET", expires_in: int = 3600,
336
+ response_headers: Optional[Dict[str, str]] = None,
337
+ auth_tenant_id: Optional[str] = None,
338
+ auth_company_id: Optional[str] = None,
339
+ doc_id: Optional[str] = None) -> Optional[str]:
340
+ """通过工厂类生成单据文件的预签名URL
341
+
342
+ Args:
343
+ filename: 文件名
344
+ method: HTTP方法,支持 GET、PUT、POST、DELETE
345
+ expires_in: 过期时间(秒),默认3600秒(1小时)
346
+ response_headers: 响应头设置
347
+ auth_tenant_id: 租户ID(可选)
348
+ auth_company_id: 公司ID(可选)
349
+ doc_id: 单据ID(可选)
350
+
351
+ Returns:
352
+ Optional[str]: 预签名URL,失败时返回None
353
+ """
354
+ storage = cls.get_instance()
355
+ return storage.generate_presigned_doc_url(
356
+ filename=filename,
357
+ method=method,
358
+ expires_in=expires_in,
359
+ response_headers=response_headers,
360
+ auth_tenant_id=auth_tenant_id,
361
+ auth_company_id=auth_company_id,
362
+ doc_id=doc_id
363
+ )
258
364
 
259
365
  # 导出工厂类
260
366
  __all__ = ['ObjectStorage', 'ObjectStorageFactory', 'StorageConfig']
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: fiuai-s3
3
- Version: 0.3.9
3
+ Version: 0.4.2
4
4
  Summary: 一个支持阿里云OSS和MinIO的对象存储抽象包
5
5
  Project-URL: Homepage, https://github.com/fiuai-sz/fiuai-s3
6
6
  Project-URL: Repository, https://github.com/fiuai-sz/fiuai-s3.git
@@ -0,0 +1,11 @@
1
+ fiuai_s3/__init__.py,sha256=BZvQEEefO33hqV8ZcT0HSLtW0XKsw8KpoxBinHTIlzo,421
2
+ fiuai_s3/object_storage.py,sha256=1vPiFFK1eb9_tF-fSn2_CBqpWtbm5WsgSvGk3VEOvvo,14169
3
+ fiuai_s3/type.py,sha256=L1h3SQh7_NhWfjWPa1MMgGoxM7g6wQF26qg5WsERt6U,981
4
+ fiuai_s3/alicloud/__init__.py,sha256=mmrCrFp5DzRF5fViJDq7_LpsqCViwTPXOPz4qoaSscI,218
5
+ fiuai_s3/alicloud/alicloud_storage.py,sha256=DieaILMmPXYU8-xbZIZbdkmju3PXEVDWXAQ7qAtuJdg,10417
6
+ fiuai_s3/minio/__init__.py,sha256=hOmpUkTq8TPgYOxfeOMcWq1_YsJ2r8Zf9VTX3w_v1Lk,209
7
+ fiuai_s3/minio/minio_storage.py,sha256=z_LvuL_CGr0bisCF9vYGwHdqJbohYi9qQFevGV4JhyM,14281
8
+ fiuai_s3-0.4.2.dist-info/METADATA,sha256=0KxOv7GE5LS5N0zPxcTvx63oAR2dP0FjhSHpeMNc8XE,18727
9
+ fiuai_s3-0.4.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
10
+ fiuai_s3-0.4.2.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
11
+ fiuai_s3-0.4.2.dist-info/RECORD,,
@@ -1,11 +0,0 @@
1
- fiuai_s3/__init__.py,sha256=tLlqnMEl4K7R4jg2GbvGZanRsis1vm7KFKSc5R_wRUE,421
2
- fiuai_s3/object_storage.py,sha256=nSXpB39Xt6RGg_QR4qU8rs7g8ZNwLjhqi9d5wOi4iTo,9479
3
- fiuai_s3/type.py,sha256=L1h3SQh7_NhWfjWPa1MMgGoxM7g6wQF26qg5WsERt6U,981
4
- fiuai_s3/alicloud/__init__.py,sha256=mmrCrFp5DzRF5fViJDq7_LpsqCViwTPXOPz4qoaSscI,218
5
- fiuai_s3/alicloud/alicloud_storage.py,sha256=d24AFYDs7RsTsfL9IiVOxYlGyLzsaUa_WUYD5VPLP4s,6035
6
- fiuai_s3/minio/__init__.py,sha256=hOmpUkTq8TPgYOxfeOMcWq1_YsJ2r8Zf9VTX3w_v1Lk,209
7
- fiuai_s3/minio/minio_storage.py,sha256=-bkxf6GSfPRpRIBbUzb1rHB8YAXqW1EuorLpjXrEV_c,10003
8
- fiuai_s3-0.3.9.dist-info/METADATA,sha256=y0Ca-vsvRWe9uVJ_Y4QV7sFaC-9xZ-OIg076h9eCKrk,18727
9
- fiuai_s3-0.3.9.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
10
- fiuai_s3-0.3.9.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
11
- fiuai_s3-0.3.9.dist-info/RECORD,,