tamar-file-hub-client 0.2.1__py3-none-any.whl → 0.2.3__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 tamar-file-hub-client might be problematic. Click here for more details.
- file_hub_client/rpc/gen/file_service_pb2.py +82 -82
- file_hub_client/rpc/protos/file_service.proto +1 -0
- file_hub_client/services/file/async_blob_service.py +27 -3
- file_hub_client/services/file/sync_blob_service.py +28 -4
- file_hub_client/utils/logging.py +11 -15
- file_hub_client/utils/upload_helper.py +67 -3
- tamar_file_hub_client-0.2.3.dist-info/METADATA +704 -0
- {tamar_file_hub_client-0.2.1.dist-info → tamar_file_hub_client-0.2.3.dist-info}/RECORD +10 -10
- tamar_file_hub_client-0.2.1.dist-info/METADATA +0 -2640
- {tamar_file_hub_client-0.2.1.dist-info → tamar_file_hub_client-0.2.3.dist-info}/WHEEL +0 -0
- {tamar_file_hub_client-0.2.1.dist-info → tamar_file_hub_client-0.2.3.dist-info}/top_level.txt +0 -0
|
@@ -9,11 +9,61 @@ import asyncio
|
|
|
9
9
|
import aiohttp
|
|
10
10
|
import requests
|
|
11
11
|
from pathlib import Path
|
|
12
|
-
from typing import Union, BinaryIO, Optional, Callable, Dict, Any, AsyncGenerator
|
|
12
|
+
from typing import Union, BinaryIO, Optional, Callable, Dict, Any, AsyncGenerator, Tuple
|
|
13
13
|
from dataclasses import dataclass
|
|
14
14
|
import hashlib
|
|
15
15
|
|
|
16
16
|
|
|
17
|
+
def detect_storage_type(url: str) -> str:
|
|
18
|
+
"""
|
|
19
|
+
根据URL检测存储类型
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
url: 上传URL
|
|
23
|
+
|
|
24
|
+
Returns:
|
|
25
|
+
存储类型: 'gcs'、'oss' 或 'unknown'
|
|
26
|
+
"""
|
|
27
|
+
if 'storage.googleapis.com' in url or 'storage.cloud.google.com' in url:
|
|
28
|
+
return 'gcs'
|
|
29
|
+
elif 'aliyuncs.com' in url:
|
|
30
|
+
return 'oss'
|
|
31
|
+
else:
|
|
32
|
+
return 'gcs'
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def get_forbid_overwrite_headers(url: str, forbid_overwrite: bool = False) -> Dict[str, str]:
|
|
36
|
+
"""
|
|
37
|
+
获取防止覆盖的headers
|
|
38
|
+
|
|
39
|
+
Args:
|
|
40
|
+
url: 上传URL
|
|
41
|
+
forbid_overwrite: 是否防止覆盖
|
|
42
|
+
|
|
43
|
+
Returns:
|
|
44
|
+
包含防止覆盖header的字典
|
|
45
|
+
|
|
46
|
+
Note:
|
|
47
|
+
- GCS: 需要在HTTP header中添加 x-goog-if-generation-match: 0
|
|
48
|
+
- OSS: 需要在HTTP header中添加 x-oss-forbid-overwrite: true
|
|
49
|
+
"""
|
|
50
|
+
if not forbid_overwrite:
|
|
51
|
+
return {}
|
|
52
|
+
|
|
53
|
+
storage_type = detect_storage_type(url)
|
|
54
|
+
|
|
55
|
+
if storage_type == 'gcs':
|
|
56
|
+
return {
|
|
57
|
+
'x-goog-if-generation-match': '0'
|
|
58
|
+
}
|
|
59
|
+
elif storage_type == 'oss':
|
|
60
|
+
return {
|
|
61
|
+
'x-oss-forbid-overwrite': 'true'
|
|
62
|
+
}
|
|
63
|
+
else:
|
|
64
|
+
return {}
|
|
65
|
+
|
|
66
|
+
|
|
17
67
|
@dataclass
|
|
18
68
|
class UploadProgress:
|
|
19
69
|
"""上传进度信息"""
|
|
@@ -127,10 +177,11 @@ class HttpUploader:
|
|
|
127
177
|
progress_callback: Optional[Callable[[UploadProgress], None]] = None,
|
|
128
178
|
total_size: Optional[int] = None,
|
|
129
179
|
is_resume: bool = False,
|
|
180
|
+
forbid_overwrite: bool = False,
|
|
130
181
|
) -> requests.Response:
|
|
131
182
|
"""
|
|
132
183
|
上传文件到指定URL
|
|
133
|
-
|
|
184
|
+
|
|
134
185
|
Args:
|
|
135
186
|
url: 上传URL
|
|
136
187
|
content: 文件内容
|
|
@@ -138,9 +189,15 @@ class HttpUploader:
|
|
|
138
189
|
headers: 请求头
|
|
139
190
|
progress_callback: 进度回调函数
|
|
140
191
|
is_resume: 是否断点续传
|
|
192
|
+
forbid_overwrite: 是否防止覆盖(添加相应的header)
|
|
141
193
|
"""
|
|
142
194
|
headers = headers or {}
|
|
143
195
|
|
|
196
|
+
# 添加防止覆盖的headers
|
|
197
|
+
if forbid_overwrite:
|
|
198
|
+
forbid_headers = get_forbid_overwrite_headers(url, forbid_overwrite)
|
|
199
|
+
headers.update(forbid_headers)
|
|
200
|
+
|
|
144
201
|
# 获取文件大小(不生成 chunk,避免提前读取)
|
|
145
202
|
final_total_size = self._calculate_total_size(content) if total_size is None else total_size
|
|
146
203
|
|
|
@@ -360,19 +417,26 @@ class AsyncHttpUploader:
|
|
|
360
417
|
progress_callback: Optional[Callable[[UploadProgress], None]] = None,
|
|
361
418
|
total_size: Optional[int] = None,
|
|
362
419
|
is_resume: bool = False,
|
|
420
|
+
forbid_overwrite: bool = False,
|
|
363
421
|
) -> aiohttp.ClientResponse:
|
|
364
422
|
"""
|
|
365
423
|
异步上传文件到指定URL
|
|
366
|
-
|
|
424
|
+
|
|
367
425
|
Args:
|
|
368
426
|
url: 上传URL
|
|
369
427
|
content: 文件内容
|
|
370
428
|
headers: 请求头
|
|
371
429
|
progress_callback: 进度回调函数
|
|
372
430
|
is_resume: 是否断点续传
|
|
431
|
+
forbid_overwrite: 是否防止覆盖(添加相应的header)
|
|
373
432
|
"""
|
|
374
433
|
headers = headers or {}
|
|
375
434
|
|
|
435
|
+
# 添加防止覆盖的headers
|
|
436
|
+
if forbid_overwrite:
|
|
437
|
+
forbid_headers = get_forbid_overwrite_headers(url, forbid_overwrite)
|
|
438
|
+
headers.update(forbid_headers)
|
|
439
|
+
|
|
376
440
|
# 获取文件大小(避免读取内容)
|
|
377
441
|
final_total_size = total_size or await self._calculate_total_size(content)
|
|
378
442
|
|