tamar-file-hub-client 0.1.3__tar.gz → 0.1.4__tar.gz

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.
Files changed (63) hide show
  1. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/PKG-INFO +162 -1
  2. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/README.md +161 -0
  3. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/client.py +24 -4
  4. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/rpc/async_client.py +31 -4
  5. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/rpc/gen/file_service_pb2.py +23 -5
  6. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/rpc/gen/file_service_pb2_grpc.py +173 -0
  7. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/rpc/protos/file_service.proto +66 -0
  8. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/rpc/sync_client.py +31 -4
  9. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/schemas/__init__.py +10 -0
  10. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/schemas/context.py +171 -160
  11. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/schemas/file.py +44 -0
  12. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/services/file/async_blob_service.py +259 -8
  13. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/services/file/async_file_service.py +217 -0
  14. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/services/file/sync_blob_service.py +260 -8
  15. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/services/file/sync_file_service.py +217 -0
  16. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/utils/__init__.py +14 -0
  17. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/utils/file_utils.py +186 -153
  18. tamar_file_hub_client-0.1.4/file_hub_client/utils/ip_detector.py +226 -0
  19. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/setup.py +1 -1
  20. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/tamar_file_hub_client.egg-info/PKG-INFO +162 -1
  21. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/tamar_file_hub_client.egg-info/SOURCES.txt +1 -0
  22. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/MANIFEST.in +0 -0
  23. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/__init__.py +0 -0
  24. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/enums/__init__.py +0 -0
  25. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/enums/export_format.py +0 -0
  26. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/enums/role.py +0 -0
  27. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/enums/upload_mode.py +0 -0
  28. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/errors/__init__.py +0 -0
  29. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/errors/exceptions.py +0 -0
  30. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/py.typed +0 -0
  31. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/rpc/__init__.py +0 -0
  32. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/rpc/gen/__init__.py +0 -0
  33. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/rpc/gen/folder_service_pb2.py +0 -0
  34. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/rpc/gen/folder_service_pb2_grpc.py +0 -0
  35. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/rpc/gen/taple_service_pb2.py +0 -0
  36. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/rpc/gen/taple_service_pb2_grpc.py +0 -0
  37. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/rpc/interceptors.py +0 -0
  38. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/rpc/protos/folder_service.proto +0 -0
  39. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/rpc/protos/taple_service.proto +0 -0
  40. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/schemas/folder.py +0 -0
  41. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/schemas/taple.py +0 -0
  42. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/services/__init__.py +0 -0
  43. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/services/file/__init__.py +0 -0
  44. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/services/file/base_file_service.py +0 -0
  45. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/services/folder/__init__.py +0 -0
  46. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/services/folder/async_folder_service.py +0 -0
  47. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/services/folder/sync_folder_service.py +0 -0
  48. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/services/taple/__init__.py +0 -0
  49. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/services/taple/async_taple_service.py +0 -0
  50. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/services/taple/base_taple_service.py +0 -0
  51. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/services/taple/idempotent_taple_mixin.py +0 -0
  52. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/services/taple/sync_taple_service.py +0 -0
  53. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/utils/converter.py +0 -0
  54. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/utils/download_helper.py +0 -0
  55. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/utils/idempotency.py +0 -0
  56. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/utils/logging.py +0 -0
  57. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/utils/retry.py +0 -0
  58. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/utils/smart_retry.py +0 -0
  59. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/file_hub_client/utils/upload_helper.py +0 -0
  60. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/setup.cfg +0 -0
  61. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/tamar_file_hub_client.egg-info/dependency_links.txt +0 -0
  62. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/tamar_file_hub_client.egg-info/requires.txt +0 -0
  63. {tamar_file_hub_client-0.1.3 → tamar_file_hub_client-0.1.4}/tamar_file_hub_client.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tamar-file-hub-client
3
- Version: 0.1.3
3
+ Version: 0.1.4
4
4
  Summary: A Python SDK for gRPC-based file management system
5
5
  Home-page: https://github.com/Tamar-Edge-AI/file-hub-client
6
6
  Author: Oscar Ou
@@ -60,6 +60,7 @@ Dynamic: summary
60
60
  - 🔁 **自动重试**:连接失败时自动重试,提高可靠性
61
61
  - 📝 **类型注解**:完整的类型提示支持
62
62
  - 🧩 **模块化设计**:清晰的代码结构,易于扩展
63
+ - 🎨 **图片和视频压缩**:支持多种规格的媒体文件压缩变体生成和管理
63
64
  - 🏗️ **分层服务架构**:文件服务分为传统文件(blob)和自定义类型(结构化数据),每种类型独立服务,语义清晰
64
65
  - 🔧 **环境变量配置**:支持通过环境变量配置所有参数
65
66
  - 👤 **用户上下文管理**:支持区分资源所有权(ownership)和操作者(operator)
@@ -209,6 +210,8 @@ File Hub Client 采用分层服务架构,将文件服务按类型和语义进
209
210
  - 智能选择上传模式(根据文件大小)
210
211
  - 生成上传/下载 URL
211
212
  - 支持临时文件上传
213
+ - **媒体文件压缩**:支持图片和视频的多规格压缩变体生成
214
+ - **压缩管理**:获取压缩状态、管理变体、触发重新压缩
212
215
  - 适用类型:PDF、图片、视频、音频、压缩包等
213
216
  - **file_service**: 处理文件元数据操作(所有类型通用)
214
217
  - 获取、重命名、删除文件
@@ -243,6 +246,11 @@ File Hub Client 采用分层服务架构,将文件服务按类型和语义进
243
246
  - `UploadUrlResponse`: URL上传响应
244
247
  - `ShareLinkRequest`: 分享链接请求
245
248
  - `FileListResponse`: 文件列表响应
249
+ - `CompressedVariant`: 压缩变体信息
250
+ - `CompressionStatusResponse`: 压缩状态响应
251
+ - `GetVariantsResponse`: 获取变体响应
252
+ - `RecompressionResponse`: 重新压缩响应
253
+ - `VariantDownloadUrlResponse`: 变体下载URL响应
246
254
 
247
255
  - **folder.py**: 文件夹相关的数据模型
248
256
  - `FolderInfo`: 文件夹信息
@@ -837,6 +845,149 @@ with TamarFileHubClient() as client:
837
845
  - 错误信息通过 `error` 字段返回
838
846
  - 建议在批量操作时做好错误处理和重试逻辑
839
847
 
848
+ ### 媒体文件压缩服务
849
+
850
+ File Hub Client 支持图片和视频文件的自动压缩处理,提供多种规格的压缩变体以满足不同使用场景的需求。
851
+
852
+ #### 获取文件压缩状态
853
+
854
+ ```python
855
+ from file_hub_client import AsyncTamarFileHubClient
856
+
857
+ async with AsyncTamarFileHubClient() as client:
858
+ client.set_user_context(org_id="123", user_id="456")
859
+
860
+ # 获取文件压缩状态
861
+ status = await client.blobs.get_compression_status(file_id="file-001")
862
+
863
+ print(f"压缩状态: {status.status}") # pending, processing, completed, failed
864
+ if status.error_message:
865
+ print(f"错误信息: {status.error_message}")
866
+
867
+ # 查看可用的压缩变体
868
+ for variant in status.variants:
869
+ print(f"变体: {variant.variant_name}")
870
+ print(f" 类型: {variant.variant_type}") # image, video, thumbnail
871
+ print(f" 尺寸: {variant.width}x{variant.height}")
872
+ print(f" 大小: {variant.file_size} bytes")
873
+ print(f" 格式: {variant.format}")
874
+ print(f" 压缩比: {variant.compression_ratio:.2f}")
875
+ ```
876
+
877
+ #### 获取压缩变体列表
878
+
879
+ ```python
880
+ # 获取所有压缩变体
881
+ variants = await client.blobs.get_compressed_variants(file_id="file-001")
882
+
883
+ # 按类型过滤变体
884
+ image_variants = await client.blobs.get_compressed_variants(
885
+ file_id="file-001",
886
+ variant_type="image" # image, video, thumbnail
887
+ )
888
+
889
+ # 处理变体信息
890
+ for variant in variants.variants:
891
+ print(f"变体名称: {variant.variant_name}") # large, medium, small, thumbnail
892
+ print(f"媒体类型: {variant.media_type}")
893
+ print(f"文件格式: {variant.format}")
894
+ if variant.quality:
895
+ print(f"质量: {variant.quality}")
896
+ if variant.duration:
897
+ print(f"时长: {variant.duration}秒")
898
+ if variant.bitrate:
899
+ print(f"比特率: {variant.bitrate}")
900
+ ```
901
+
902
+ #### 下载压缩变体
903
+
904
+ ```python
905
+ # 生成压缩变体的下载URL
906
+ variant_url = await client.blobs.generate_variant_download_url(
907
+ file_id="file-001",
908
+ variant_name="medium", # large, medium, small, thumbnail
909
+ expire_seconds=3600, # URL有效期
910
+ is_cdn=True # 是否使用CDN
911
+ )
912
+
913
+ print(f"下载URL: {variant_url.url}")
914
+ if variant_url.error:
915
+ print(f"生成URL错误: {variant_url.error}")
916
+
917
+ # 查看变体详细信息
918
+ if variant_url.variant_info:
919
+ info = variant_url.variant_info
920
+ print(f"变体信息:")
921
+ print(f" 尺寸: {info.width}x{info.height}")
922
+ print(f" 格式: {info.format}")
923
+ print(f" 文件大小: {info.file_size} bytes")
924
+ ```
925
+
926
+ #### 触发重新压缩
927
+
928
+ ```python
929
+ # 触发文件重新压缩(当需要更新压缩设置时)
930
+ recompression = await client.blobs.trigger_recompression(
931
+ file_id="file-001",
932
+ force_reprocess=False # 是否强制重新处理
933
+ )
934
+
935
+ print(f"任务ID: {recompression.task_id}")
936
+ print(f"状态: {recompression.status}")
937
+
938
+ # 监控压缩进度
939
+ import asyncio
940
+ while True:
941
+ status = await client.blobs.get_compression_status(file_id="file-001")
942
+ print(f"当前状态: {status.status}")
943
+
944
+ if status.status in ["completed", "failed"]:
945
+ break
946
+
947
+ await asyncio.sleep(5) # 等待5秒后再次检查
948
+ ```
949
+
950
+ #### 同步客户端压缩服务
951
+
952
+ ```python
953
+ from file_hub_client import TamarFileHubClient
954
+
955
+ with TamarFileHubClient() as client:
956
+ client.set_user_context(org_id="123", user_id="456")
957
+
958
+ # 所有压缩服务方法都有对应的同步版本
959
+ status = client.blobs.get_compression_status(file_id="file-001")
960
+ variants = client.blobs.get_compressed_variants(file_id="file-001")
961
+ recompression = client.blobs.trigger_recompression(file_id="file-001")
962
+ variant_url = client.blobs.generate_variant_download_url(
963
+ file_id="file-001",
964
+ variant_name="thumbnail"
965
+ )
966
+ ```
967
+
968
+ #### 压缩服务使用场景
969
+
970
+ 1. **多设备适配**:
971
+ - `large` - 高分辨率显示设备
972
+ - `medium` - 标准桌面和平板
973
+ - `small` - 手机端显示
974
+ - `thumbnail` - 缩略图预览
975
+
976
+ 2. **带宽优化**:
977
+ - 根据网络状况选择合适的变体
978
+ - 移动端使用压缩变体节省流量
979
+ - 预览场景使用缩略图快速加载
980
+
981
+ 3. **存储优化**:
982
+ - 自动生成多种规格,无需手动处理
983
+ - 智能压缩算法平衡质量和大小
984
+ - 支持视频和图片的不同压缩策略
985
+
986
+ 4. **性能优化**:
987
+ - 异步压缩处理,不阻塞上传流程
988
+ - 支持重新压缩以应用新的压缩设置
989
+ - 批量状态查询减少网络请求
990
+
840
991
  ### 文件管理操作
841
992
 
842
993
  File Hub Client 提供了完整的文件管理功能,通过 `files` 服务访问:
@@ -2174,6 +2325,16 @@ MIT License
2174
2325
 
2175
2326
  ## 更新日志
2176
2327
 
2328
+ ### v0.0.6 (2025-08)
2329
+ - 新增媒体文件压缩服务功能
2330
+ - 支持获取文件压缩状态 (get_compression_status)
2331
+ - 支持获取压缩变体列表 (get_compressed_variants)
2332
+ - 支持触发文件重新压缩 (trigger_recompression)
2333
+ - 支持生成变体下载URL (generate_variant_download_url)
2334
+ - 添加压缩相关数据模型 (CompressedVariant 等)
2335
+ - 在所有文件服务类中实现压缩功能支持
2336
+ - 更新文档包含压缩服务使用示例
2337
+
2177
2338
  ### v0.0.5 (2025-01)
2178
2339
  - 新增批量下载URL生成接口 (batch_generate_download_url)
2179
2340
  - 新增GCS URL获取接口 (get_gcs_url, batch_get_gcs_url)
@@ -14,6 +14,7 @@
14
14
  - 🔁 **自动重试**:连接失败时自动重试,提高可靠性
15
15
  - 📝 **类型注解**:完整的类型提示支持
16
16
  - 🧩 **模块化设计**:清晰的代码结构,易于扩展
17
+ - 🎨 **图片和视频压缩**:支持多种规格的媒体文件压缩变体生成和管理
17
18
  - 🏗️ **分层服务架构**:文件服务分为传统文件(blob)和自定义类型(结构化数据),每种类型独立服务,语义清晰
18
19
  - 🔧 **环境变量配置**:支持通过环境变量配置所有参数
19
20
  - 👤 **用户上下文管理**:支持区分资源所有权(ownership)和操作者(operator)
@@ -163,6 +164,8 @@ File Hub Client 采用分层服务架构,将文件服务按类型和语义进
163
164
  - 智能选择上传模式(根据文件大小)
164
165
  - 生成上传/下载 URL
165
166
  - 支持临时文件上传
167
+ - **媒体文件压缩**:支持图片和视频的多规格压缩变体生成
168
+ - **压缩管理**:获取压缩状态、管理变体、触发重新压缩
166
169
  - 适用类型:PDF、图片、视频、音频、压缩包等
167
170
  - **file_service**: 处理文件元数据操作(所有类型通用)
168
171
  - 获取、重命名、删除文件
@@ -197,6 +200,11 @@ File Hub Client 采用分层服务架构,将文件服务按类型和语义进
197
200
  - `UploadUrlResponse`: URL上传响应
198
201
  - `ShareLinkRequest`: 分享链接请求
199
202
  - `FileListResponse`: 文件列表响应
203
+ - `CompressedVariant`: 压缩变体信息
204
+ - `CompressionStatusResponse`: 压缩状态响应
205
+ - `GetVariantsResponse`: 获取变体响应
206
+ - `RecompressionResponse`: 重新压缩响应
207
+ - `VariantDownloadUrlResponse`: 变体下载URL响应
200
208
 
201
209
  - **folder.py**: 文件夹相关的数据模型
202
210
  - `FolderInfo`: 文件夹信息
@@ -791,6 +799,149 @@ with TamarFileHubClient() as client:
791
799
  - 错误信息通过 `error` 字段返回
792
800
  - 建议在批量操作时做好错误处理和重试逻辑
793
801
 
802
+ ### 媒体文件压缩服务
803
+
804
+ File Hub Client 支持图片和视频文件的自动压缩处理,提供多种规格的压缩变体以满足不同使用场景的需求。
805
+
806
+ #### 获取文件压缩状态
807
+
808
+ ```python
809
+ from file_hub_client import AsyncTamarFileHubClient
810
+
811
+ async with AsyncTamarFileHubClient() as client:
812
+ client.set_user_context(org_id="123", user_id="456")
813
+
814
+ # 获取文件压缩状态
815
+ status = await client.blobs.get_compression_status(file_id="file-001")
816
+
817
+ print(f"压缩状态: {status.status}") # pending, processing, completed, failed
818
+ if status.error_message:
819
+ print(f"错误信息: {status.error_message}")
820
+
821
+ # 查看可用的压缩变体
822
+ for variant in status.variants:
823
+ print(f"变体: {variant.variant_name}")
824
+ print(f" 类型: {variant.variant_type}") # image, video, thumbnail
825
+ print(f" 尺寸: {variant.width}x{variant.height}")
826
+ print(f" 大小: {variant.file_size} bytes")
827
+ print(f" 格式: {variant.format}")
828
+ print(f" 压缩比: {variant.compression_ratio:.2f}")
829
+ ```
830
+
831
+ #### 获取压缩变体列表
832
+
833
+ ```python
834
+ # 获取所有压缩变体
835
+ variants = await client.blobs.get_compressed_variants(file_id="file-001")
836
+
837
+ # 按类型过滤变体
838
+ image_variants = await client.blobs.get_compressed_variants(
839
+ file_id="file-001",
840
+ variant_type="image" # image, video, thumbnail
841
+ )
842
+
843
+ # 处理变体信息
844
+ for variant in variants.variants:
845
+ print(f"变体名称: {variant.variant_name}") # large, medium, small, thumbnail
846
+ print(f"媒体类型: {variant.media_type}")
847
+ print(f"文件格式: {variant.format}")
848
+ if variant.quality:
849
+ print(f"质量: {variant.quality}")
850
+ if variant.duration:
851
+ print(f"时长: {variant.duration}秒")
852
+ if variant.bitrate:
853
+ print(f"比特率: {variant.bitrate}")
854
+ ```
855
+
856
+ #### 下载压缩变体
857
+
858
+ ```python
859
+ # 生成压缩变体的下载URL
860
+ variant_url = await client.blobs.generate_variant_download_url(
861
+ file_id="file-001",
862
+ variant_name="medium", # large, medium, small, thumbnail
863
+ expire_seconds=3600, # URL有效期
864
+ is_cdn=True # 是否使用CDN
865
+ )
866
+
867
+ print(f"下载URL: {variant_url.url}")
868
+ if variant_url.error:
869
+ print(f"生成URL错误: {variant_url.error}")
870
+
871
+ # 查看变体详细信息
872
+ if variant_url.variant_info:
873
+ info = variant_url.variant_info
874
+ print(f"变体信息:")
875
+ print(f" 尺寸: {info.width}x{info.height}")
876
+ print(f" 格式: {info.format}")
877
+ print(f" 文件大小: {info.file_size} bytes")
878
+ ```
879
+
880
+ #### 触发重新压缩
881
+
882
+ ```python
883
+ # 触发文件重新压缩(当需要更新压缩设置时)
884
+ recompression = await client.blobs.trigger_recompression(
885
+ file_id="file-001",
886
+ force_reprocess=False # 是否强制重新处理
887
+ )
888
+
889
+ print(f"任务ID: {recompression.task_id}")
890
+ print(f"状态: {recompression.status}")
891
+
892
+ # 监控压缩进度
893
+ import asyncio
894
+ while True:
895
+ status = await client.blobs.get_compression_status(file_id="file-001")
896
+ print(f"当前状态: {status.status}")
897
+
898
+ if status.status in ["completed", "failed"]:
899
+ break
900
+
901
+ await asyncio.sleep(5) # 等待5秒后再次检查
902
+ ```
903
+
904
+ #### 同步客户端压缩服务
905
+
906
+ ```python
907
+ from file_hub_client import TamarFileHubClient
908
+
909
+ with TamarFileHubClient() as client:
910
+ client.set_user_context(org_id="123", user_id="456")
911
+
912
+ # 所有压缩服务方法都有对应的同步版本
913
+ status = client.blobs.get_compression_status(file_id="file-001")
914
+ variants = client.blobs.get_compressed_variants(file_id="file-001")
915
+ recompression = client.blobs.trigger_recompression(file_id="file-001")
916
+ variant_url = client.blobs.generate_variant_download_url(
917
+ file_id="file-001",
918
+ variant_name="thumbnail"
919
+ )
920
+ ```
921
+
922
+ #### 压缩服务使用场景
923
+
924
+ 1. **多设备适配**:
925
+ - `large` - 高分辨率显示设备
926
+ - `medium` - 标准桌面和平板
927
+ - `small` - 手机端显示
928
+ - `thumbnail` - 缩略图预览
929
+
930
+ 2. **带宽优化**:
931
+ - 根据网络状况选择合适的变体
932
+ - 移动端使用压缩变体节省流量
933
+ - 预览场景使用缩略图快速加载
934
+
935
+ 3. **存储优化**:
936
+ - 自动生成多种规格,无需手动处理
937
+ - 智能压缩算法平衡质量和大小
938
+ - 支持视频和图片的不同压缩策略
939
+
940
+ 4. **性能优化**:
941
+ - 异步压缩处理,不阻塞上传流程
942
+ - 支持重新压缩以应用新的压缩设置
943
+ - 批量状态查询减少网络请求
944
+
794
945
  ### 文件管理操作
795
946
 
796
947
  File Hub Client 提供了完整的文件管理功能,通过 `files` 服务访问:
@@ -2128,6 +2279,16 @@ MIT License
2128
2279
 
2129
2280
  ## 更新日志
2130
2281
 
2282
+ ### v0.0.6 (2025-08)
2283
+ - 新增媒体文件压缩服务功能
2284
+ - 支持获取文件压缩状态 (get_compression_status)
2285
+ - 支持获取压缩变体列表 (get_compressed_variants)
2286
+ - 支持触发文件重新压缩 (trigger_recompression)
2287
+ - 支持生成变体下载URL (generate_variant_download_url)
2288
+ - 添加压缩相关数据模型 (CompressedVariant 等)
2289
+ - 在所有文件服务类中实现压缩功能支持
2290
+ - 更新文档包含压缩服务使用示例
2291
+
2131
2292
  ### v0.0.5 (2025-01)
2132
2293
  - 新增批量下载URL生成接口 (batch_generate_download_url)
2133
2294
  - 新增GCS URL获取接口 (get_gcs_url, batch_get_gcs_url)
@@ -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.set_user_context(org_id, user_id, role, actor_id)
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
- metadata.update(kwargs)
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\x45mpty2\xae\x07\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.FileListResponseb\x06proto3')
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['_EMPTY']._serialized_start=3082
89
- _globals['_EMPTY']._serialized_end=3089
90
- _globals['_FILESERVICE']._serialized_start=3092
91
- _globals['_FILESERVICE']._serialized_end=4034
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)