tamar-file-hub-client 0.1.3__py3-none-any.whl → 0.1.4__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.
- file_hub_client/client.py +24 -4
- file_hub_client/rpc/async_client.py +31 -4
- file_hub_client/rpc/gen/file_service_pb2.py +23 -5
- file_hub_client/rpc/gen/file_service_pb2_grpc.py +173 -0
- file_hub_client/rpc/protos/file_service.proto +66 -0
- file_hub_client/rpc/sync_client.py +31 -4
- file_hub_client/schemas/__init__.py +10 -0
- file_hub_client/schemas/context.py +171 -160
- file_hub_client/schemas/file.py +44 -0
- file_hub_client/services/file/async_blob_service.py +259 -8
- file_hub_client/services/file/async_file_service.py +217 -0
- file_hub_client/services/file/sync_blob_service.py +260 -8
- file_hub_client/services/file/sync_file_service.py +217 -0
- file_hub_client/utils/__init__.py +14 -0
- file_hub_client/utils/file_utils.py +186 -153
- file_hub_client/utils/ip_detector.py +226 -0
- {tamar_file_hub_client-0.1.3.dist-info → tamar_file_hub_client-0.1.4.dist-info}/METADATA +162 -1
- {tamar_file_hub_client-0.1.3.dist-info → tamar_file_hub_client-0.1.4.dist-info}/RECORD +20 -19
- {tamar_file_hub_client-0.1.3.dist-info → tamar_file_hub_client-0.1.4.dist-info}/WHEEL +0 -0
- {tamar_file_hub_client-0.1.3.dist-info → tamar_file_hub_client-0.1.4.dist-info}/top_level.txt +0 -0
file_hub_client/client.py
CHANGED
@@ -157,7 +157,7 @@ class AsyncTamarFileHubClient:
|
|
157
157
|
self._taple_service = AsyncTapleService(self._client)
|
158
158
|
return self._taple_service
|
159
159
|
|
160
|
-
def set_user_context(self, org_id: str, user_id: str, role: Role = Role.ACCOUNT, actor_id: Optional[str] = None):
|
160
|
+
def set_user_context(self, org_id: str, user_id: str, role: Role = Role.ACCOUNT, actor_id: Optional[str] = None, user_ip: Optional[str] = None):
|
161
161
|
"""
|
162
162
|
设置用户上下文信息
|
163
163
|
|
@@ -166,8 +166,18 @@ class AsyncTamarFileHubClient:
|
|
166
166
|
user_id: 用户ID
|
167
167
|
role: 用户角色(默认为 ACCOUNT)
|
168
168
|
actor_id: 操作者ID(如果不同于 user_id)
|
169
|
+
user_ip: 用户IP地址(实际请求用户的IP,如前端用户的IP)
|
169
170
|
"""
|
170
|
-
self._client.set_user_context(org_id, user_id, role, actor_id)
|
171
|
+
self._client.set_user_context(org_id, user_id, role, actor_id, user_ip)
|
172
|
+
|
173
|
+
def set_user_ip(self, user_ip: Optional[str]):
|
174
|
+
"""
|
175
|
+
设置或更新用户IP地址
|
176
|
+
|
177
|
+
Args:
|
178
|
+
user_ip: 用户IP地址(实际请求用户的IP,如前端用户的IP)
|
179
|
+
"""
|
180
|
+
self._client.set_user_ip(user_ip)
|
171
181
|
|
172
182
|
def get_user_context(self) -> Optional[UserContext]:
|
173
183
|
"""获取当前用户上下文"""
|
@@ -364,7 +374,7 @@ class TamarFileHubClient:
|
|
364
374
|
self._taple_service = SyncTapleService(self._client)
|
365
375
|
return self._taple_service
|
366
376
|
|
367
|
-
def set_user_context(self, org_id: str, user_id: str, role: Role = Role.ACCOUNT, actor_id: Optional[str] = None):
|
377
|
+
def set_user_context(self, org_id: str, user_id: str, role: Role = Role.ACCOUNT, actor_id: Optional[str] = None, user_ip: Optional[str] = None):
|
368
378
|
"""
|
369
379
|
设置用户上下文信息
|
370
380
|
|
@@ -373,8 +383,18 @@ class TamarFileHubClient:
|
|
373
383
|
user_id: 用户ID
|
374
384
|
role: 用户角色(默认为 ACCOUNT)
|
375
385
|
actor_id: 操作者ID(如果不同于 user_id)
|
386
|
+
user_ip: 用户IP地址(实际请求用户的IP,如前端用户的IP)
|
387
|
+
"""
|
388
|
+
self._client.set_user_context(org_id, user_id, role, actor_id, user_ip)
|
389
|
+
|
390
|
+
def set_user_ip(self, user_ip: Optional[str]):
|
391
|
+
"""
|
392
|
+
设置或更新用户IP地址
|
393
|
+
|
394
|
+
Args:
|
395
|
+
user_ip: 用户IP地址(实际请求用户的IP,如前端用户的IP)
|
376
396
|
"""
|
377
|
-
self._client.
|
397
|
+
self._client.set_user_ip(user_ip)
|
378
398
|
|
379
399
|
def get_user_context(self) -> Optional[UserContext]:
|
380
400
|
"""获取当前用户上下文"""
|
@@ -281,8 +281,17 @@ class AsyncGrpcClient:
|
|
281
281
|
# 添加默认元数据
|
282
282
|
metadata.update(self.default_metadata)
|
283
283
|
|
284
|
-
#
|
285
|
-
|
284
|
+
# 自动检测用户真实IP
|
285
|
+
from ..utils.ip_detector import get_current_user_ip
|
286
|
+
auto_detected_ip = get_current_user_ip()
|
287
|
+
if auto_detected_ip and 'x-user-ip' not in metadata:
|
288
|
+
# 只有在没有设置过user_ip的情况下才使用自动检测的IP
|
289
|
+
metadata['x-user-ip'] = auto_detected_ip
|
290
|
+
|
291
|
+
# 添加/覆盖传入的元数据,但跳过None值以避免覆盖有效的默认值
|
292
|
+
for k, v in kwargs.items():
|
293
|
+
if v is not None:
|
294
|
+
metadata[k] = v
|
286
295
|
|
287
296
|
# 处理 request_id(优先级:显式传入 > metadata中的x-request-id > RequestContext > 自动生成)
|
288
297
|
if request_id is not None:
|
@@ -314,7 +323,7 @@ class AsyncGrpcClient:
|
|
314
323
|
"""
|
315
324
|
self.default_metadata.update(kwargs)
|
316
325
|
|
317
|
-
def set_user_context(self, org_id: str, user_id: str, role: Role = Role.ACCOUNT, actor_id: Optional[str] = None):
|
326
|
+
def set_user_context(self, org_id: str, user_id: str, role: Role = Role.ACCOUNT, actor_id: Optional[str] = None, user_ip: Optional[str] = None):
|
318
327
|
"""
|
319
328
|
设置用户上下文信息
|
320
329
|
|
@@ -323,16 +332,34 @@ class AsyncGrpcClient:
|
|
323
332
|
user_id: 用户ID
|
324
333
|
role: 用户角色(默认为 ACCOUNT)
|
325
334
|
actor_id: 操作者ID(如果不同于 user_id)
|
335
|
+
user_ip: 用户IP地址(实际请求用户的IP,如前端用户的IP)
|
326
336
|
"""
|
327
337
|
self._user_context = UserContext(
|
328
338
|
org_id=org_id,
|
329
339
|
user_id=user_id,
|
330
340
|
role=role,
|
331
|
-
actor_id=actor_id
|
341
|
+
actor_id=actor_id,
|
342
|
+
user_ip=user_ip
|
332
343
|
)
|
333
344
|
# 更新到默认元数据
|
334
345
|
self.update_default_metadata(**self._user_context.to_metadata())
|
335
346
|
|
347
|
+
def set_user_ip(self, user_ip: Optional[str]):
|
348
|
+
"""
|
349
|
+
设置或更新用户IP地址
|
350
|
+
|
351
|
+
Args:
|
352
|
+
user_ip: 用户IP地址(实际请求用户的IP,如前端用户的IP)
|
353
|
+
"""
|
354
|
+
if self._user_context:
|
355
|
+
self._user_context.user_ip = user_ip
|
356
|
+
# 先移除旧的x-user-ip(如果存在)
|
357
|
+
self.default_metadata.pop('x-user-ip', None)
|
358
|
+
# 更新到默认元数据(只有非None值会被添加)
|
359
|
+
self.update_default_metadata(**self._user_context.to_metadata())
|
360
|
+
else:
|
361
|
+
raise ValueError("必须先调用 set_user_context 设置用户上下文,然后才能设置用户IP")
|
362
|
+
|
336
363
|
def get_user_context(self) -> Optional[UserContext]:
|
337
364
|
"""获取当前用户上下文"""
|
338
365
|
return self._user_context
|
@@ -26,7 +26,7 @@ from google.protobuf import timestamp_pb2 as google_dot_protobuf_dot_timestamp__
|
|
26
26
|
from google.protobuf import struct_pb2 as google_dot_protobuf_dot_struct__pb2
|
27
27
|
|
28
28
|
|
29
|
-
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x12\x66ile_service.proto\x12\x04\x66ile\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1cgoogle/protobuf/struct.proto\"\xab\x01\n\x04\x46ile\x12\n\n\x02id\x18\x01 \x01(\t\x12\x11\n\tfolder_id\x18\x02 \x01(\t\x12\x11\n\tfile_name\x18\x03 \x01(\t\x12\x11\n\tfile_type\x18\x04 \x01(\t\x12.\n\ncreated_at\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nupdated_at\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\"\xb7\x02\n\nUploadFile\x12\n\n\x02id\x18\x01 \x01(\t\x12\x11\n\tfolder_id\x18\x02 \x01(\t\x12\x0f\n\x07\x66ile_id\x18\x03 \x01(\t\x12\x14\n\x0cstorage_type\x18\x04 \x01(\t\x12\x13\n\x0bstored_name\x18\x05 \x01(\t\x12\x13\n\x0bstored_path\x18\x06 \x01(\t\x12\x11\n\tfile_name\x18\x07 \x01(\t\x12\x11\n\tfile_size\x18\x08 \x01(\x03\x12\x10\n\x08\x66ile_ext\x18\t \x01(\t\x12\x11\n\tmime_type\x18\n \x01(\t\x12\x0e\n\x06status\x18\x0b \x01(\t\x12.\n\ncreated_at\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nupdated_at\x18\r \x01(\x0b\x32\x1a.google.protobuf.Timestamp\"\x9f\x02\n\x11UploadFileRequest\x12\x16\n\tfolder_id\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x11\n\tfile_name\x18\x02 \x01(\t\x12\x0f\n\x07\x63ontent\x18\x03 \x01(\x0c\x12\x11\n\tfile_type\x18\x04 \x01(\t\x12\x11\n\tmime_type\x18\x05 \x01(\t\x12\x19\n\x0cis_temporary\x18\x06 \x01(\x08H\x01\x88\x01\x01\x12\x1b\n\x0e\x65xpire_seconds\x18\x07 \x01(\x05H\x02\x88\x01\x01\x12#\n\x16keep_original_filename\x18\x08 \x01(\x08H\x03\x88\x01\x01\x42\x0c\n\n_folder_idB\x0f\n\r_is_temporaryB\x11\n\x0f_expire_secondsB\x19\n\x17_keep_original_filename\"\xb3\x02\n\x10UploadUrlRequest\x12\x16\n\tfolder_id\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x11\n\tfile_name\x18\x02 \x01(\t\x12\x11\n\tfile_type\x18\x03 \x01(\t\x12\x11\n\tmime_type\x18\x04 \x01(\t\x12\x11\n\tfile_size\x18\x05 \x01(\x03\x12\x11\n\tfile_hash\x18\x06 \x01(\t\x12\x19\n\x0cis_temporary\x18\x07 \x01(\x08H\x01\x88\x01\x01\x12\x1b\n\x0e\x65xpire_seconds\x18\x08 \x01(\x05H\x02\x88\x01\x01\x12#\n\x16keep_original_filename\x18\t \x01(\x08H\x03\x88\x01\x01\x42\x0c\n\n_folder_idB\x0f\n\r_is_temporaryB\x11\n\x0f_expire_secondsB\x19\n\x17_keep_original_filename\")\n\x16UploadCompletedRequest\x12\x0f\n\x07\x66ile_id\x18\x01 \x01(\t\"u\n\x12\x44ownloadUrlRequest\x12\x0f\n\x07\x66ile_id\x18\x01 \x01(\t\x12\x13\n\x06is_cdn\x18\x03 \x01(\x08H\x00\x88\x01\x01\x12\x1b\n\x0e\x65xpire_seconds\x18\x02 \x01(\x05H\x01\x88\x01\x01\x42\t\n\x07_is_cdnB\x11\n\x0f_expire_seconds\"\xd4\x01\n\x10ShareLinkRequest\x12\x0f\n\x07\x66ile_id\x18\x01 \x01(\t\x12\x11\n\tis_public\x18\x02 \x01(\x08\x12\x14\n\x0c\x61\x63\x63\x65ss_scope\x18\x03 \x01(\t\x12\x1b\n\x0e\x65xpire_seconds\x18\x04 \x01(\x05H\x00\x88\x01\x01\x12\x17\n\nmax_access\x18\x05 \x01(\x05H\x01\x88\x01\x01\x12\x1b\n\x0eshare_password\x18\x06 \x01(\tH\x02\x88\x01\x01\x42\x11\n\x0f_expire_secondsB\r\n\x0b_max_accessB\x11\n\x0f_share_password\"\x82\x01\n\x10\x46ileVisitRequest\x12\x15\n\rfile_share_id\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63\x63\x65ss_type\x18\x02 \x01(\t\x12\x17\n\x0f\x61\x63\x63\x65ss_duration\x18\x03 \x01(\x05\x12)\n\x08metadata\x18\x04 \x01(\x0b\x32\x17.google.protobuf.Struct\"!\n\x0eGetFileRequest\x12\x0f\n\x07\x66ile_id\x18\x01 \x01(\t\"6\n\x11RenameFileRequest\x12\x0f\n\x07\x66ile_id\x18\x01 \x01(\t\x12\x10\n\x08new_name\x18\x02 \x01(\t\"$\n\x11\x44\x65leteFileRequest\x12\x0f\n\x07\x66ile_id\x18\x01 \x01(\t\"\x8d\x02\n\x10ListFilesRequest\x12\x16\n\tfolder_id\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x16\n\tfile_name\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x11\n\tfile_type\x18\x03 \x03(\t\x12\x1c\n\x0f\x63reated_by_role\x18\x04 \x01(\tH\x02\x88\x01\x01\x12\x17\n\ncreated_by\x18\x05 \x01(\tH\x03\x88\x01\x01\x12\x16\n\tpage_size\x18\x06 \x01(\x05H\x04\x88\x01\x01\x12\x11\n\x04page\x18\x07 \x01(\x05H\x05\x88\x01\x01\x42\x0c\n\n_folder_idB\x0c\n\n_file_nameB\x12\n\x10_created_by_roleB\r\n\x0b_created_byB\x0c\n\n_page_sizeB\x07\n\x05_page\"{\n\x17\x42\x61tchDownloadUrlRequest\x12\x10\n\x08\x66ile_ids\x18\x01 \x03(\t\x12\x13\n\x06is_cdn\x18\x02 \x01(\x08H\x00\x88\x01\x01\x12\x1b\n\x0e\x65xpire_seconds\x18\x03 \x01(\x05H\x01\x88\x01\x01\x42\t\n\x07_is_cdnB\x11\n\x0f_expire_seconds\"#\n\x10GetGcsUrlRequest\x12\x0f\n\x07\x66ile_id\x18\x01 \x01(\t\")\n\x15\x42\x61tchGetGcsUrlRequest\x12\x10\n\x08\x66ile_ids\x18\x01 \x03(\t\"U\n\x12UploadFileResponse\x12\x18\n\x04\x66ile\x18\x01 \x01(\x0b\x32\n.file.File\x12%\n\x0bupload_file\x18\x02 \x01(\x0b\x32\x10.file.UploadFile\"a\n\x11UploadUrlResponse\x12\x18\n\x04\x66ile\x18\x01 \x01(\x0b\x32\n.file.File\x12%\n\x0bupload_file\x18\x02 \x01(\x0b\x32\x10.file.UploadFile\x12\x0b\n\x03url\x18\x03 \x01(\t\"\"\n\x13\x44ownloadUrlResponse\x12\x0b\n\x03url\x18\x01 \x01(\t\"*\n\x11ShareLinkResponse\x12\x15\n\rfile_share_id\x18\x01 \x01(\t\"-\n\x10\x46ileListResponse\x12\x19\n\x05\x66iles\x18\x01 \x03(\x0b\x32\n.file.File\"g\n\x0fGetFileResponse\x12\x18\n\x04\x66ile\x18\x01 \x01(\x0b\x32\n.file.File\x12*\n\x0bupload_file\x18\x02 \x01(\x0b\x32\x10.file.UploadFileH\x00\x88\x01\x01\x42\x0e\n\x0c_upload_file\"H\n\x18\x42\x61tchDownloadUrlResponse\x12,\n\rdownload_urls\x18\x01 \x03(\x0b\x32\x15.file.DownloadUrlInfo\"M\n\x0f\x44ownloadUrlInfo\x12\x0f\n\x07\x66ile_id\x18\x01 \x01(\t\x12\x0b\n\x03url\x18\x02 \x01(\t\x12\x12\n\x05\x65rror\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x08\n\x06_error\"7\n\x11GetGcsUrlResponse\x12\x0f\n\x07gcs_url\x18\x01 \x01(\t\x12\x11\n\tmime_type\x18\x02 \x01(\t\"<\n\x16\x42\x61tchGetGcsUrlResponse\x12\"\n\x08gcs_urls\x18\x01 \x03(\x0b\x32\x10.file.GcsUrlInfo\"_\n\nGcsUrlInfo\x12\x0f\n\x07\x66ile_id\x18\x01 \x01(\t\x12\x0f\n\x07gcs_url\x18\x02 \x01(\t\x12\x11\n\tmime_type\x18\x03 \x01(\t\x12\x12\n\x05\x65rror\x18\x04 \x01(\tH\x00\x88\x01\x01\x42\x08\n\x06_error\"\x07\n\x05\
|
29
|
+
DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x12\x66ile_service.proto\x12\x04\x66ile\x1a\x1fgoogle/protobuf/timestamp.proto\x1a\x1cgoogle/protobuf/struct.proto\"\xab\x01\n\x04\x46ile\x12\n\n\x02id\x18\x01 \x01(\t\x12\x11\n\tfolder_id\x18\x02 \x01(\t\x12\x11\n\tfile_name\x18\x03 \x01(\t\x12\x11\n\tfile_type\x18\x04 \x01(\t\x12.\n\ncreated_at\x18\x05 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nupdated_at\x18\x06 \x01(\x0b\x32\x1a.google.protobuf.Timestamp\"\xb7\x02\n\nUploadFile\x12\n\n\x02id\x18\x01 \x01(\t\x12\x11\n\tfolder_id\x18\x02 \x01(\t\x12\x0f\n\x07\x66ile_id\x18\x03 \x01(\t\x12\x14\n\x0cstorage_type\x18\x04 \x01(\t\x12\x13\n\x0bstored_name\x18\x05 \x01(\t\x12\x13\n\x0bstored_path\x18\x06 \x01(\t\x12\x11\n\tfile_name\x18\x07 \x01(\t\x12\x11\n\tfile_size\x18\x08 \x01(\x03\x12\x10\n\x08\x66ile_ext\x18\t \x01(\t\x12\x11\n\tmime_type\x18\n \x01(\t\x12\x0e\n\x06status\x18\x0b \x01(\t\x12.\n\ncreated_at\x18\x0c \x01(\x0b\x32\x1a.google.protobuf.Timestamp\x12.\n\nupdated_at\x18\r \x01(\x0b\x32\x1a.google.protobuf.Timestamp\"\x9f\x02\n\x11UploadFileRequest\x12\x16\n\tfolder_id\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x11\n\tfile_name\x18\x02 \x01(\t\x12\x0f\n\x07\x63ontent\x18\x03 \x01(\x0c\x12\x11\n\tfile_type\x18\x04 \x01(\t\x12\x11\n\tmime_type\x18\x05 \x01(\t\x12\x19\n\x0cis_temporary\x18\x06 \x01(\x08H\x01\x88\x01\x01\x12\x1b\n\x0e\x65xpire_seconds\x18\x07 \x01(\x05H\x02\x88\x01\x01\x12#\n\x16keep_original_filename\x18\x08 \x01(\x08H\x03\x88\x01\x01\x42\x0c\n\n_folder_idB\x0f\n\r_is_temporaryB\x11\n\x0f_expire_secondsB\x19\n\x17_keep_original_filename\"\xb3\x02\n\x10UploadUrlRequest\x12\x16\n\tfolder_id\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x11\n\tfile_name\x18\x02 \x01(\t\x12\x11\n\tfile_type\x18\x03 \x01(\t\x12\x11\n\tmime_type\x18\x04 \x01(\t\x12\x11\n\tfile_size\x18\x05 \x01(\x03\x12\x11\n\tfile_hash\x18\x06 \x01(\t\x12\x19\n\x0cis_temporary\x18\x07 \x01(\x08H\x01\x88\x01\x01\x12\x1b\n\x0e\x65xpire_seconds\x18\x08 \x01(\x05H\x02\x88\x01\x01\x12#\n\x16keep_original_filename\x18\t \x01(\x08H\x03\x88\x01\x01\x42\x0c\n\n_folder_idB\x0f\n\r_is_temporaryB\x11\n\x0f_expire_secondsB\x19\n\x17_keep_original_filename\")\n\x16UploadCompletedRequest\x12\x0f\n\x07\x66ile_id\x18\x01 \x01(\t\"u\n\x12\x44ownloadUrlRequest\x12\x0f\n\x07\x66ile_id\x18\x01 \x01(\t\x12\x13\n\x06is_cdn\x18\x03 \x01(\x08H\x00\x88\x01\x01\x12\x1b\n\x0e\x65xpire_seconds\x18\x02 \x01(\x05H\x01\x88\x01\x01\x42\t\n\x07_is_cdnB\x11\n\x0f_expire_seconds\"\xd4\x01\n\x10ShareLinkRequest\x12\x0f\n\x07\x66ile_id\x18\x01 \x01(\t\x12\x11\n\tis_public\x18\x02 \x01(\x08\x12\x14\n\x0c\x61\x63\x63\x65ss_scope\x18\x03 \x01(\t\x12\x1b\n\x0e\x65xpire_seconds\x18\x04 \x01(\x05H\x00\x88\x01\x01\x12\x17\n\nmax_access\x18\x05 \x01(\x05H\x01\x88\x01\x01\x12\x1b\n\x0eshare_password\x18\x06 \x01(\tH\x02\x88\x01\x01\x42\x11\n\x0f_expire_secondsB\r\n\x0b_max_accessB\x11\n\x0f_share_password\"\x82\x01\n\x10\x46ileVisitRequest\x12\x15\n\rfile_share_id\x18\x01 \x01(\t\x12\x13\n\x0b\x61\x63\x63\x65ss_type\x18\x02 \x01(\t\x12\x17\n\x0f\x61\x63\x63\x65ss_duration\x18\x03 \x01(\x05\x12)\n\x08metadata\x18\x04 \x01(\x0b\x32\x17.google.protobuf.Struct\"!\n\x0eGetFileRequest\x12\x0f\n\x07\x66ile_id\x18\x01 \x01(\t\"6\n\x11RenameFileRequest\x12\x0f\n\x07\x66ile_id\x18\x01 \x01(\t\x12\x10\n\x08new_name\x18\x02 \x01(\t\"$\n\x11\x44\x65leteFileRequest\x12\x0f\n\x07\x66ile_id\x18\x01 \x01(\t\"\x8d\x02\n\x10ListFilesRequest\x12\x16\n\tfolder_id\x18\x01 \x01(\tH\x00\x88\x01\x01\x12\x16\n\tfile_name\x18\x02 \x01(\tH\x01\x88\x01\x01\x12\x11\n\tfile_type\x18\x03 \x03(\t\x12\x1c\n\x0f\x63reated_by_role\x18\x04 \x01(\tH\x02\x88\x01\x01\x12\x17\n\ncreated_by\x18\x05 \x01(\tH\x03\x88\x01\x01\x12\x16\n\tpage_size\x18\x06 \x01(\x05H\x04\x88\x01\x01\x12\x11\n\x04page\x18\x07 \x01(\x05H\x05\x88\x01\x01\x42\x0c\n\n_folder_idB\x0c\n\n_file_nameB\x12\n\x10_created_by_roleB\r\n\x0b_created_byB\x0c\n\n_page_sizeB\x07\n\x05_page\"{\n\x17\x42\x61tchDownloadUrlRequest\x12\x10\n\x08\x66ile_ids\x18\x01 \x03(\t\x12\x13\n\x06is_cdn\x18\x02 \x01(\x08H\x00\x88\x01\x01\x12\x1b\n\x0e\x65xpire_seconds\x18\x03 \x01(\x05H\x01\x88\x01\x01\x42\t\n\x07_is_cdnB\x11\n\x0f_expire_seconds\"#\n\x10GetGcsUrlRequest\x12\x0f\n\x07\x66ile_id\x18\x01 \x01(\t\")\n\x15\x42\x61tchGetGcsUrlRequest\x12\x10\n\x08\x66ile_ids\x18\x01 \x03(\t\"U\n\x12UploadFileResponse\x12\x18\n\x04\x66ile\x18\x01 \x01(\x0b\x32\n.file.File\x12%\n\x0bupload_file\x18\x02 \x01(\x0b\x32\x10.file.UploadFile\"a\n\x11UploadUrlResponse\x12\x18\n\x04\x66ile\x18\x01 \x01(\x0b\x32\n.file.File\x12%\n\x0bupload_file\x18\x02 \x01(\x0b\x32\x10.file.UploadFile\x12\x0b\n\x03url\x18\x03 \x01(\t\"\"\n\x13\x44ownloadUrlResponse\x12\x0b\n\x03url\x18\x01 \x01(\t\"*\n\x11ShareLinkResponse\x12\x15\n\rfile_share_id\x18\x01 \x01(\t\"-\n\x10\x46ileListResponse\x12\x19\n\x05\x66iles\x18\x01 \x03(\x0b\x32\n.file.File\"g\n\x0fGetFileResponse\x12\x18\n\x04\x66ile\x18\x01 \x01(\x0b\x32\n.file.File\x12*\n\x0bupload_file\x18\x02 \x01(\x0b\x32\x10.file.UploadFileH\x00\x88\x01\x01\x42\x0e\n\x0c_upload_file\"H\n\x18\x42\x61tchDownloadUrlResponse\x12,\n\rdownload_urls\x18\x01 \x03(\x0b\x32\x15.file.DownloadUrlInfo\"M\n\x0f\x44ownloadUrlInfo\x12\x0f\n\x07\x66ile_id\x18\x01 \x01(\t\x12\x0b\n\x03url\x18\x02 \x01(\t\x12\x12\n\x05\x65rror\x18\x03 \x01(\tH\x00\x88\x01\x01\x42\x08\n\x06_error\"7\n\x11GetGcsUrlResponse\x12\x0f\n\x07gcs_url\x18\x01 \x01(\t\x12\x11\n\tmime_type\x18\x02 \x01(\t\"<\n\x16\x42\x61tchGetGcsUrlResponse\x12\"\n\x08gcs_urls\x18\x01 \x03(\x0b\x32\x10.file.GcsUrlInfo\"_\n\nGcsUrlInfo\x12\x0f\n\x07\x66ile_id\x18\x01 \x01(\t\x12\x0f\n\x07gcs_url\x18\x02 \x01(\t\x12\x11\n\tmime_type\x18\x03 \x01(\t\x12\x12\n\x05\x65rror\x18\x04 \x01(\tH\x00\x88\x01\x01\x42\x08\n\x06_error\"+\n\x18\x43ompressionStatusRequest\x12\x0f\n\x07\x66ile_id\x18\x01 \x01(\t\"\x84\x01\n\x19\x43ompressionStatusResponse\x12\x0e\n\x06status\x18\x01 \x01(\t\x12\x1a\n\rerror_message\x18\x02 \x01(\tH\x00\x88\x01\x01\x12)\n\x08variants\x18\x03 \x03(\x0b\x32\x17.file.CompressedVariantB\x10\n\x0e_error_message\"Q\n\x12GetVariantsRequest\x12\x0f\n\x07\x66ile_id\x18\x01 \x01(\t\x12\x19\n\x0cvariant_type\x18\x02 \x01(\tH\x00\x88\x01\x01\x42\x0f\n\r_variant_type\"@\n\x13GetVariantsResponse\x12)\n\x08variants\x18\x01 \x03(\x0b\x32\x17.file.CompressedVariant\"\xc7\x02\n\x11\x43ompressedVariant\x12\x14\n\x0cvariant_name\x18\x01 \x01(\t\x12\x14\n\x0cvariant_type\x18\x02 \x01(\t\x12\x12\n\nmedia_type\x18\x03 \x01(\t\x12\r\n\x05width\x18\x04 \x01(\x05\x12\x0e\n\x06height\x18\x05 \x01(\x05\x12\x11\n\tfile_size\x18\x06 \x01(\x03\x12\x0e\n\x06\x66ormat\x18\x07 \x01(\t\x12\x14\n\x07quality\x18\x08 \x01(\x05H\x00\x88\x01\x01\x12\x15\n\x08\x64uration\x18\t \x01(\x01H\x01\x88\x01\x01\x12\x14\n\x07\x62itrate\x18\n \x01(\x03H\x02\x88\x01\x01\x12\x10\n\x03\x66ps\x18\x0b \x01(\x05H\x03\x88\x01\x01\x12\x19\n\x11\x63ompression_ratio\x18\x0c \x01(\x01\x12\x13\n\x0bstored_path\x18\r \x01(\tB\n\n\x08_qualityB\x0b\n\t_durationB\n\n\x08_bitrateB\x06\n\x04_fps\"Y\n\x14RecompressionRequest\x12\x0f\n\x07\x66ile_id\x18\x01 \x01(\t\x12\x1c\n\x0f\x66orce_reprocess\x18\x02 \x01(\x08H\x00\x88\x01\x01\x42\x12\n\x10_force_reprocess\"8\n\x15RecompressionResponse\x12\x0f\n\x07task_id\x18\x01 \x01(\t\x12\x0e\n\x06status\x18\x02 \x01(\t\"\x92\x01\n\x19VariantDownloadUrlRequest\x12\x0f\n\x07\x66ile_id\x18\x01 \x01(\t\x12\x14\n\x0cvariant_name\x18\x02 \x01(\t\x12\x1b\n\x0e\x65xpire_seconds\x18\x03 \x01(\x05H\x00\x88\x01\x01\x12\x13\n\x06is_cdn\x18\x04 \x01(\x08H\x01\x88\x01\x01\x42\x11\n\x0f_expire_secondsB\t\n\x07_is_cdn\"\x8c\x01\n\x1aVariantDownloadUrlResponse\x12\x0b\n\x03url\x18\x01 \x01(\t\x12\x12\n\x05\x65rror\x18\x02 \x01(\tH\x00\x88\x01\x01\x12\x32\n\x0cvariant_info\x18\x03 \x01(\x0b\x32\x17.file.CompressedVariantH\x01\x88\x01\x01\x42\x08\n\x06_errorB\x0f\n\r_variant_info\"\x07\n\x05\x45mpty2\x87\n\n\x0b\x46ileService\x12?\n\nUploadFile\x12\x17.file.UploadFileRequest\x1a\x18.file.UploadFileResponse\x12\x44\n\x11GenerateUploadUrl\x12\x16.file.UploadUrlRequest\x1a\x17.file.UploadUrlResponse\x12M\n\x1aGenerateResumableUploadUrl\x12\x16.file.UploadUrlRequest\x1a\x17.file.UploadUrlResponse\x12\x43\n\x16\x43onfirmUploadCompleted\x12\x1c.file.UploadCompletedRequest\x1a\x0b.file.Empty\x12J\n\x13GenerateDownloadUrl\x12\x18.file.DownloadUrlRequest\x1a\x19.file.DownloadUrlResponse\x12Y\n\x18\x42\x61tchGenerateDownloadUrl\x12\x1d.file.BatchDownloadUrlRequest\x1a\x1e.file.BatchDownloadUrlResponse\x12<\n\tGetGcsUrl\x12\x16.file.GetGcsUrlRequest\x1a\x17.file.GetGcsUrlResponse\x12K\n\x0e\x42\x61tchGetGcsUrl\x12\x1b.file.BatchGetGcsUrlRequest\x1a\x1c.file.BatchGetGcsUrlResponse\x12\x44\n\x11GenerateShareLink\x12\x16.file.ShareLinkRequest\x1a\x17.file.ShareLinkResponse\x12\x30\n\tVisitFile\x12\x16.file.FileVisitRequest\x1a\x0b.file.Empty\x12\x36\n\x07GetFile\x12\x14.file.GetFileRequest\x1a\x15.file.GetFileResponse\x12\x31\n\nRenameFile\x12\x17.file.RenameFileRequest\x1a\n.file.File\x12\x32\n\nDeleteFile\x12\x17.file.DeleteFileRequest\x1a\x0b.file.Empty\x12;\n\tListFiles\x12\x16.file.ListFilesRequest\x1a\x16.file.FileListResponse\x12W\n\x14GetCompressionStatus\x12\x1e.file.CompressionStatusRequest\x1a\x1f.file.CompressionStatusResponse\x12L\n\x15GetCompressedVariants\x12\x18.file.GetVariantsRequest\x1a\x19.file.GetVariantsResponse\x12O\n\x14TriggerRecompression\x12\x1a.file.RecompressionRequest\x1a\x1b.file.RecompressionResponse\x12_\n\x1aGenerateVariantDownloadUrl\x12\x1f.file.VariantDownloadUrlRequest\x1a .file.VariantDownloadUrlResponseb\x06proto3')
|
30
30
|
|
31
31
|
_globals = globals()
|
32
32
|
_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
|
@@ -85,8 +85,26 @@ if not _descriptor._USE_C_DESCRIPTORS:
|
|
85
85
|
_globals['_BATCHGETGCSURLRESPONSE']._serialized_end=2983
|
86
86
|
_globals['_GCSURLINFO']._serialized_start=2985
|
87
87
|
_globals['_GCSURLINFO']._serialized_end=3080
|
88
|
-
_globals['
|
89
|
-
_globals['
|
90
|
-
_globals['
|
91
|
-
_globals['
|
88
|
+
_globals['_COMPRESSIONSTATUSREQUEST']._serialized_start=3082
|
89
|
+
_globals['_COMPRESSIONSTATUSREQUEST']._serialized_end=3125
|
90
|
+
_globals['_COMPRESSIONSTATUSRESPONSE']._serialized_start=3128
|
91
|
+
_globals['_COMPRESSIONSTATUSRESPONSE']._serialized_end=3260
|
92
|
+
_globals['_GETVARIANTSREQUEST']._serialized_start=3262
|
93
|
+
_globals['_GETVARIANTSREQUEST']._serialized_end=3343
|
94
|
+
_globals['_GETVARIANTSRESPONSE']._serialized_start=3345
|
95
|
+
_globals['_GETVARIANTSRESPONSE']._serialized_end=3409
|
96
|
+
_globals['_COMPRESSEDVARIANT']._serialized_start=3412
|
97
|
+
_globals['_COMPRESSEDVARIANT']._serialized_end=3739
|
98
|
+
_globals['_RECOMPRESSIONREQUEST']._serialized_start=3741
|
99
|
+
_globals['_RECOMPRESSIONREQUEST']._serialized_end=3830
|
100
|
+
_globals['_RECOMPRESSIONRESPONSE']._serialized_start=3832
|
101
|
+
_globals['_RECOMPRESSIONRESPONSE']._serialized_end=3888
|
102
|
+
_globals['_VARIANTDOWNLOADURLREQUEST']._serialized_start=3891
|
103
|
+
_globals['_VARIANTDOWNLOADURLREQUEST']._serialized_end=4037
|
104
|
+
_globals['_VARIANTDOWNLOADURLRESPONSE']._serialized_start=4040
|
105
|
+
_globals['_VARIANTDOWNLOADURLRESPONSE']._serialized_end=4180
|
106
|
+
_globals['_EMPTY']._serialized_start=4182
|
107
|
+
_globals['_EMPTY']._serialized_end=4189
|
108
|
+
_globals['_FILESERVICE']._serialized_start=4192
|
109
|
+
_globals['_FILESERVICE']._serialized_end=5479
|
92
110
|
# @@protoc_insertion_point(module_scope)
|
@@ -106,6 +106,26 @@ class FileServiceStub(object):
|
|
106
106
|
request_serializer=file__service__pb2.ListFilesRequest.SerializeToString,
|
107
107
|
response_deserializer=file__service__pb2.FileListResponse.FromString,
|
108
108
|
_registered_method=True)
|
109
|
+
self.GetCompressionStatus = channel.unary_unary(
|
110
|
+
'/file.FileService/GetCompressionStatus',
|
111
|
+
request_serializer=file__service__pb2.CompressionStatusRequest.SerializeToString,
|
112
|
+
response_deserializer=file__service__pb2.CompressionStatusResponse.FromString,
|
113
|
+
_registered_method=True)
|
114
|
+
self.GetCompressedVariants = channel.unary_unary(
|
115
|
+
'/file.FileService/GetCompressedVariants',
|
116
|
+
request_serializer=file__service__pb2.GetVariantsRequest.SerializeToString,
|
117
|
+
response_deserializer=file__service__pb2.GetVariantsResponse.FromString,
|
118
|
+
_registered_method=True)
|
119
|
+
self.TriggerRecompression = channel.unary_unary(
|
120
|
+
'/file.FileService/TriggerRecompression',
|
121
|
+
request_serializer=file__service__pb2.RecompressionRequest.SerializeToString,
|
122
|
+
response_deserializer=file__service__pb2.RecompressionResponse.FromString,
|
123
|
+
_registered_method=True)
|
124
|
+
self.GenerateVariantDownloadUrl = channel.unary_unary(
|
125
|
+
'/file.FileService/GenerateVariantDownloadUrl',
|
126
|
+
request_serializer=file__service__pb2.VariantDownloadUrlRequest.SerializeToString,
|
127
|
+
response_deserializer=file__service__pb2.VariantDownloadUrlResponse.FromString,
|
128
|
+
_registered_method=True)
|
109
129
|
|
110
130
|
|
111
131
|
class FileServiceServicer(object):
|
@@ -197,6 +217,31 @@ class FileServiceServicer(object):
|
|
197
217
|
context.set_details('Method not implemented!')
|
198
218
|
raise NotImplementedError('Method not implemented!')
|
199
219
|
|
220
|
+
def GetCompressionStatus(self, request, context):
|
221
|
+
"""压缩服务相关API
|
222
|
+
"""
|
223
|
+
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
224
|
+
context.set_details('Method not implemented!')
|
225
|
+
raise NotImplementedError('Method not implemented!')
|
226
|
+
|
227
|
+
def GetCompressedVariants(self, request, context):
|
228
|
+
"""Missing associated documentation comment in .proto file."""
|
229
|
+
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
230
|
+
context.set_details('Method not implemented!')
|
231
|
+
raise NotImplementedError('Method not implemented!')
|
232
|
+
|
233
|
+
def TriggerRecompression(self, request, context):
|
234
|
+
"""Missing associated documentation comment in .proto file."""
|
235
|
+
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
236
|
+
context.set_details('Method not implemented!')
|
237
|
+
raise NotImplementedError('Method not implemented!')
|
238
|
+
|
239
|
+
def GenerateVariantDownloadUrl(self, request, context):
|
240
|
+
"""Missing associated documentation comment in .proto file."""
|
241
|
+
context.set_code(grpc.StatusCode.UNIMPLEMENTED)
|
242
|
+
context.set_details('Method not implemented!')
|
243
|
+
raise NotImplementedError('Method not implemented!')
|
244
|
+
|
200
245
|
|
201
246
|
def add_FileServiceServicer_to_server(servicer, server):
|
202
247
|
rpc_method_handlers = {
|
@@ -270,6 +315,26 @@ def add_FileServiceServicer_to_server(servicer, server):
|
|
270
315
|
request_deserializer=file__service__pb2.ListFilesRequest.FromString,
|
271
316
|
response_serializer=file__service__pb2.FileListResponse.SerializeToString,
|
272
317
|
),
|
318
|
+
'GetCompressionStatus': grpc.unary_unary_rpc_method_handler(
|
319
|
+
servicer.GetCompressionStatus,
|
320
|
+
request_deserializer=file__service__pb2.CompressionStatusRequest.FromString,
|
321
|
+
response_serializer=file__service__pb2.CompressionStatusResponse.SerializeToString,
|
322
|
+
),
|
323
|
+
'GetCompressedVariants': grpc.unary_unary_rpc_method_handler(
|
324
|
+
servicer.GetCompressedVariants,
|
325
|
+
request_deserializer=file__service__pb2.GetVariantsRequest.FromString,
|
326
|
+
response_serializer=file__service__pb2.GetVariantsResponse.SerializeToString,
|
327
|
+
),
|
328
|
+
'TriggerRecompression': grpc.unary_unary_rpc_method_handler(
|
329
|
+
servicer.TriggerRecompression,
|
330
|
+
request_deserializer=file__service__pb2.RecompressionRequest.FromString,
|
331
|
+
response_serializer=file__service__pb2.RecompressionResponse.SerializeToString,
|
332
|
+
),
|
333
|
+
'GenerateVariantDownloadUrl': grpc.unary_unary_rpc_method_handler(
|
334
|
+
servicer.GenerateVariantDownloadUrl,
|
335
|
+
request_deserializer=file__service__pb2.VariantDownloadUrlRequest.FromString,
|
336
|
+
response_serializer=file__service__pb2.VariantDownloadUrlResponse.SerializeToString,
|
337
|
+
),
|
273
338
|
}
|
274
339
|
generic_handler = grpc.method_handlers_generic_handler(
|
275
340
|
'file.FileService', rpc_method_handlers)
|
@@ -660,3 +725,111 @@ class FileService(object):
|
|
660
725
|
timeout,
|
661
726
|
metadata,
|
662
727
|
_registered_method=True)
|
728
|
+
|
729
|
+
@staticmethod
|
730
|
+
def GetCompressionStatus(request,
|
731
|
+
target,
|
732
|
+
options=(),
|
733
|
+
channel_credentials=None,
|
734
|
+
call_credentials=None,
|
735
|
+
insecure=False,
|
736
|
+
compression=None,
|
737
|
+
wait_for_ready=None,
|
738
|
+
timeout=None,
|
739
|
+
metadata=None):
|
740
|
+
return grpc.experimental.unary_unary(
|
741
|
+
request,
|
742
|
+
target,
|
743
|
+
'/file.FileService/GetCompressionStatus',
|
744
|
+
file__service__pb2.CompressionStatusRequest.SerializeToString,
|
745
|
+
file__service__pb2.CompressionStatusResponse.FromString,
|
746
|
+
options,
|
747
|
+
channel_credentials,
|
748
|
+
insecure,
|
749
|
+
call_credentials,
|
750
|
+
compression,
|
751
|
+
wait_for_ready,
|
752
|
+
timeout,
|
753
|
+
metadata,
|
754
|
+
_registered_method=True)
|
755
|
+
|
756
|
+
@staticmethod
|
757
|
+
def GetCompressedVariants(request,
|
758
|
+
target,
|
759
|
+
options=(),
|
760
|
+
channel_credentials=None,
|
761
|
+
call_credentials=None,
|
762
|
+
insecure=False,
|
763
|
+
compression=None,
|
764
|
+
wait_for_ready=None,
|
765
|
+
timeout=None,
|
766
|
+
metadata=None):
|
767
|
+
return grpc.experimental.unary_unary(
|
768
|
+
request,
|
769
|
+
target,
|
770
|
+
'/file.FileService/GetCompressedVariants',
|
771
|
+
file__service__pb2.GetVariantsRequest.SerializeToString,
|
772
|
+
file__service__pb2.GetVariantsResponse.FromString,
|
773
|
+
options,
|
774
|
+
channel_credentials,
|
775
|
+
insecure,
|
776
|
+
call_credentials,
|
777
|
+
compression,
|
778
|
+
wait_for_ready,
|
779
|
+
timeout,
|
780
|
+
metadata,
|
781
|
+
_registered_method=True)
|
782
|
+
|
783
|
+
@staticmethod
|
784
|
+
def TriggerRecompression(request,
|
785
|
+
target,
|
786
|
+
options=(),
|
787
|
+
channel_credentials=None,
|
788
|
+
call_credentials=None,
|
789
|
+
insecure=False,
|
790
|
+
compression=None,
|
791
|
+
wait_for_ready=None,
|
792
|
+
timeout=None,
|
793
|
+
metadata=None):
|
794
|
+
return grpc.experimental.unary_unary(
|
795
|
+
request,
|
796
|
+
target,
|
797
|
+
'/file.FileService/TriggerRecompression',
|
798
|
+
file__service__pb2.RecompressionRequest.SerializeToString,
|
799
|
+
file__service__pb2.RecompressionResponse.FromString,
|
800
|
+
options,
|
801
|
+
channel_credentials,
|
802
|
+
insecure,
|
803
|
+
call_credentials,
|
804
|
+
compression,
|
805
|
+
wait_for_ready,
|
806
|
+
timeout,
|
807
|
+
metadata,
|
808
|
+
_registered_method=True)
|
809
|
+
|
810
|
+
@staticmethod
|
811
|
+
def GenerateVariantDownloadUrl(request,
|
812
|
+
target,
|
813
|
+
options=(),
|
814
|
+
channel_credentials=None,
|
815
|
+
call_credentials=None,
|
816
|
+
insecure=False,
|
817
|
+
compression=None,
|
818
|
+
wait_for_ready=None,
|
819
|
+
timeout=None,
|
820
|
+
metadata=None):
|
821
|
+
return grpc.experimental.unary_unary(
|
822
|
+
request,
|
823
|
+
target,
|
824
|
+
'/file.FileService/GenerateVariantDownloadUrl',
|
825
|
+
file__service__pb2.VariantDownloadUrlRequest.SerializeToString,
|
826
|
+
file__service__pb2.VariantDownloadUrlResponse.FromString,
|
827
|
+
options,
|
828
|
+
channel_credentials,
|
829
|
+
insecure,
|
830
|
+
call_credentials,
|
831
|
+
compression,
|
832
|
+
wait_for_ready,
|
833
|
+
timeout,
|
834
|
+
metadata,
|
835
|
+
_registered_method=True)
|
@@ -22,6 +22,12 @@ service FileService {
|
|
22
22
|
rpc RenameFile (RenameFileRequest) returns (File);
|
23
23
|
rpc DeleteFile (DeleteFileRequest) returns (Empty);
|
24
24
|
rpc ListFiles (ListFilesRequest) returns (FileListResponse);
|
25
|
+
|
26
|
+
// 压缩服务相关API
|
27
|
+
rpc GetCompressionStatus (CompressionStatusRequest) returns (CompressionStatusResponse);
|
28
|
+
rpc GetCompressedVariants (GetVariantsRequest) returns (GetVariantsResponse);
|
29
|
+
rpc TriggerRecompression (RecompressionRequest) returns (RecompressionResponse);
|
30
|
+
rpc GenerateVariantDownloadUrl (VariantDownloadUrlRequest) returns (VariantDownloadUrlResponse);
|
25
31
|
}
|
26
32
|
|
27
33
|
// ========= 数据结构定义 =========
|
@@ -195,4 +201,64 @@ message GcsUrlInfo {
|
|
195
201
|
optional string error = 4;
|
196
202
|
}
|
197
203
|
|
204
|
+
// ========= 压缩服务相关结构 =========
|
205
|
+
|
206
|
+
message CompressionStatusRequest {
|
207
|
+
string file_id = 1;
|
208
|
+
}
|
209
|
+
|
210
|
+
message CompressionStatusResponse {
|
211
|
+
string status = 1; // pending, processing, completed, failed
|
212
|
+
optional string error_message = 2;
|
213
|
+
repeated CompressedVariant variants = 3;
|
214
|
+
}
|
215
|
+
|
216
|
+
message GetVariantsRequest {
|
217
|
+
string file_id = 1;
|
218
|
+
optional string variant_type = 2; // image, video, thumbnail
|
219
|
+
}
|
220
|
+
|
221
|
+
message GetVariantsResponse {
|
222
|
+
repeated CompressedVariant variants = 1;
|
223
|
+
}
|
224
|
+
|
225
|
+
message CompressedVariant {
|
226
|
+
string variant_name = 1;
|
227
|
+
string variant_type = 2;
|
228
|
+
string media_type = 3;
|
229
|
+
int32 width = 4;
|
230
|
+
int32 height = 5;
|
231
|
+
int64 file_size = 6;
|
232
|
+
string format = 7;
|
233
|
+
optional int32 quality = 8;
|
234
|
+
optional double duration = 9;
|
235
|
+
optional int64 bitrate = 10;
|
236
|
+
optional int32 fps = 11;
|
237
|
+
double compression_ratio = 12;
|
238
|
+
string stored_path = 13;
|
239
|
+
}
|
240
|
+
|
241
|
+
message RecompressionRequest {
|
242
|
+
string file_id = 1;
|
243
|
+
optional bool force_reprocess = 2;
|
244
|
+
}
|
245
|
+
|
246
|
+
message RecompressionResponse {
|
247
|
+
string task_id = 1;
|
248
|
+
string status = 2;
|
249
|
+
}
|
250
|
+
|
251
|
+
message VariantDownloadUrlRequest {
|
252
|
+
string file_id = 1;
|
253
|
+
string variant_name = 2; // large/medium/small/thumbnail
|
254
|
+
optional int32 expire_seconds = 3;
|
255
|
+
optional bool is_cdn = 4;
|
256
|
+
}
|
257
|
+
|
258
|
+
message VariantDownloadUrlResponse {
|
259
|
+
string url = 1;
|
260
|
+
optional string error = 2;
|
261
|
+
optional CompressedVariant variant_info = 3; // 返回变体详细信息
|
262
|
+
}
|
263
|
+
|
198
264
|
message Empty {}
|
@@ -284,8 +284,17 @@ class SyncGrpcClient:
|
|
284
284
|
# 添加默认元数据
|
285
285
|
metadata.update(self.default_metadata)
|
286
286
|
|
287
|
-
#
|
288
|
-
|
287
|
+
# 自动检测用户真实IP
|
288
|
+
from ..utils.ip_detector import get_current_user_ip
|
289
|
+
auto_detected_ip = get_current_user_ip()
|
290
|
+
if auto_detected_ip and 'x-user-ip' not in metadata:
|
291
|
+
# 只有在没有设置过user_ip的情况下才使用自动检测的IP
|
292
|
+
metadata['x-user-ip'] = auto_detected_ip
|
293
|
+
|
294
|
+
# 添加/覆盖传入的元数据,但跳过None值以避免覆盖有效的默认值
|
295
|
+
for k, v in kwargs.items():
|
296
|
+
if v is not None:
|
297
|
+
metadata[k] = v
|
289
298
|
|
290
299
|
# 处理 request_id(优先级:显式传入 > metadata中的x-request-id > RequestContext > 自动生成)
|
291
300
|
if request_id is not None:
|
@@ -317,7 +326,7 @@ class SyncGrpcClient:
|
|
317
326
|
"""
|
318
327
|
self.default_metadata.update(kwargs)
|
319
328
|
|
320
|
-
def set_user_context(self, org_id: str, user_id: str, role: Role = Role.ACCOUNT, actor_id: Optional[str] = None):
|
329
|
+
def set_user_context(self, org_id: str, user_id: str, role: Role = Role.ACCOUNT, actor_id: Optional[str] = None, user_ip: Optional[str] = None):
|
321
330
|
"""
|
322
331
|
设置用户上下文信息
|
323
332
|
|
@@ -326,16 +335,34 @@ class SyncGrpcClient:
|
|
326
335
|
user_id: 用户ID
|
327
336
|
role: 用户角色(默认为 ACCOUNT)
|
328
337
|
actor_id: 操作者ID(如果不同于 user_id)
|
338
|
+
user_ip: 用户IP地址(实际请求用户的IP,如前端用户的IP)
|
329
339
|
"""
|
330
340
|
self._user_context = UserContext(
|
331
341
|
org_id=org_id,
|
332
342
|
user_id=user_id,
|
333
343
|
role=role,
|
334
|
-
actor_id=actor_id
|
344
|
+
actor_id=actor_id,
|
345
|
+
user_ip=user_ip
|
335
346
|
)
|
336
347
|
# 更新到默认元数据
|
337
348
|
self.update_default_metadata(**self._user_context.to_metadata())
|
338
349
|
|
350
|
+
def set_user_ip(self, user_ip: Optional[str]):
|
351
|
+
"""
|
352
|
+
设置或更新用户IP地址
|
353
|
+
|
354
|
+
Args:
|
355
|
+
user_ip: 用户IP地址(实际请求用户的IP,如前端用户的IP)
|
356
|
+
"""
|
357
|
+
if self._user_context:
|
358
|
+
self._user_context.user_ip = user_ip
|
359
|
+
# 先移除旧的x-user-ip(如果存在)
|
360
|
+
self.default_metadata.pop('x-user-ip', None)
|
361
|
+
# 更新到默认元数据(只有非None值会被添加)
|
362
|
+
self.update_default_metadata(**self._user_context.to_metadata())
|
363
|
+
else:
|
364
|
+
raise ValueError("必须先调用 set_user_context 设置用户上下文,然后才能设置用户IP")
|
365
|
+
|
339
366
|
def get_user_context(self) -> Optional[UserContext]:
|
340
367
|
"""获取当前用户上下文"""
|
341
368
|
return self._user_context
|
@@ -16,6 +16,11 @@ from .file import (
|
|
16
16
|
GcsUrlInfo,
|
17
17
|
GetGcsUrlResponse,
|
18
18
|
BatchGcsUrlResponse,
|
19
|
+
CompressedVariant,
|
20
|
+
CompressionStatusResponse,
|
21
|
+
GetVariantsResponse,
|
22
|
+
RecompressionResponse,
|
23
|
+
VariantDownloadUrlResponse,
|
19
24
|
)
|
20
25
|
from .folder import (
|
21
26
|
FolderInfo,
|
@@ -73,6 +78,11 @@ __all__ = [
|
|
73
78
|
"GcsUrlInfo",
|
74
79
|
"GetGcsUrlResponse",
|
75
80
|
"BatchGcsUrlResponse",
|
81
|
+
"CompressedVariant",
|
82
|
+
"CompressionStatusResponse",
|
83
|
+
"GetVariantsResponse",
|
84
|
+
"RecompressionResponse",
|
85
|
+
"VariantDownloadUrlResponse",
|
76
86
|
|
77
87
|
# 文件夹相关
|
78
88
|
"FolderInfo",
|