aod-oss-client 0.1.0__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.
@@ -0,0 +1,10 @@
1
+ # OSS 凭证(OssClientConfig 不传时读取)
2
+ OSS_ACCESS_KEY_ID=your_access_key_id
3
+ OSS_ACCESS_KEY_SECRET=your_access_key_secret
4
+ OSS_REGION=cn-hangzhou
5
+ OSS_BUCKET=my-bucket
6
+
7
+ # 可选
8
+ OSS_ENDPOINT=
9
+ OSS_PUBLIC_BASE_URL=
10
+ OSS_USE_INTERNAL_ENDPOINT=false
@@ -0,0 +1,10 @@
1
+ __pycache__/
2
+ *.pyc
3
+ *.pyo
4
+ .env
5
+ .venv/
6
+ dist/
7
+ *.egg-info/
8
+ .pytest_cache/
9
+ .ruff_cache/
10
+ logs/
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 aod-oss-client
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,198 @@
1
+ Metadata-Version: 2.4
2
+ Name: aod-oss-client
3
+ Version: 0.1.0
4
+ Summary: 阿里云 OSS 上传客户端(同步 + 异步)
5
+ Author: aod-oss-client contributors
6
+ License-Expression: MIT
7
+ License-File: LICENSE
8
+ Classifier: Development Status :: 4 - Beta
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ Classifier: Programming Language :: Python :: 3.13
13
+ Classifier: Topic :: Internet :: WWW/HTTP
14
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
15
+ Requires-Python: >=3.12
16
+ Requires-Dist: aiofiles>=24.1
17
+ Requires-Dist: aiohttp>=3.9
18
+ Requires-Dist: alibabacloud-oss-v2>=1.0.0
19
+ Requires-Dist: python-dotenv>=1.0
20
+ Provides-Extra: dev
21
+ Requires-Dist: pytest-asyncio>=0.24; extra == 'dev'
22
+ Requires-Dist: pytest>=9.0; extra == 'dev'
23
+ Requires-Dist: ruff>=0.9; extra == 'dev'
24
+ Description-Content-Type: text/markdown
25
+
26
+ # aod-oss-client
27
+
28
+ 阿里云 OSS 上传客户端,同时支持 **同步** 和 **异步** 两种接口。
29
+
30
+ ## 特性
31
+
32
+ - 同步 + 异步双 API,同一 `OssClient` 实例可多次复用
33
+ - 自动选择简单上传(< 100MB)或分片上传(≥ 100MB)
34
+ - 分片并发上传,内置指数退避重试
35
+ - `content_type` 自动检测,不传自动推断
36
+ - `skip_if_exists` 支持幂等跳过
37
+ - 凭证支持显式传入 / 环境变量 / `.env` 文件
38
+ - 支持自定义域名、内网 Endpoint
39
+
40
+ ## 安装
41
+
42
+ ```bash
43
+ pip install aod-oss-client
44
+ # 或
45
+ uv add aod-oss-client
46
+ ```
47
+
48
+ ## 快速开始
49
+
50
+ ### 同步用法
51
+
52
+ ```python
53
+ from aod_oss_client import OssClient, OssClientConfig
54
+
55
+ config = OssClientConfig(bucket="my-bucket", region="cn-hangzhou")
56
+ client = OssClient(config)
57
+
58
+ r1 = client.upload_file("/data/a.geojson", "data/a.geojson")
59
+ r2 = client.upload_file("/data/b.fgb", "data/b.fgb")
60
+
61
+ print(r1.url, r2.url)
62
+ # client.close() # 可选
63
+ ```
64
+
65
+ ### 异步用法
66
+
67
+ ```python
68
+ from aod_oss_client import OssClient, OssClientConfig
69
+
70
+ config = OssClientConfig(bucket="my-bucket", region="cn-hangzhou")
71
+ client = OssClient(config)
72
+
73
+ r1 = await client.async_upload_file("/data/a.geojson", "data/a.geojson")
74
+ r2 = await client.async_upload_file("/data/b.fgb", "data/b.fgb")
75
+
76
+ print(r1.url, r2.url)
77
+ # await client.async_aclose() # 可选
78
+ ```
79
+
80
+ ### 幂等跳过
81
+
82
+ ```python
83
+ result = client.upload_file("photo.jpg", "images/photo.jpg", skip_if_exists=True)
84
+ if result.skipped:
85
+ print("文件已存在,跳过上传")
86
+ ```
87
+
88
+ ### 自定义元属性
89
+
90
+ 上传时可通过 `metadata` 参数设置 OSS 对象自定义元属性(即 `x-oss-meta-*` 头):
91
+
92
+ ```python
93
+ client.upload_file(
94
+ "data.geojson", "data.geojson",
95
+ metadata={
96
+ "source": "gps_collector",
97
+ "crs": "EPSG:4326",
98
+ "version": "2.1",
99
+ },
100
+ )
101
+ ```
102
+
103
+ 元属性会在 OSS 控制台和 GetObject 响应的 `x-oss-meta-*` 头中返回。
104
+
105
+ ### content_type 自动检测
106
+
107
+ 不传则根据文件扩展名自动推断:
108
+
109
+ ```python
110
+ client.upload_file("data.json", "data.json") # → application/json
111
+ client.upload_file("data.geojson", "data.geojson") # → application/geo+json
112
+ client.upload_file("data.bin", "data.bin") # → application/octet-stream
113
+ client.upload_file("data.fgb", "data.fgb", content_type="application/geo+json") # 手动指定
114
+ ```
115
+
116
+ ### with 语句
117
+
118
+ ```python
119
+ with OssClient(config) as client:
120
+ client.upload_file("a.txt", "a.txt")
121
+ client.upload_file("b.txt", "b.txt")
122
+ ```
123
+
124
+ ## 配置
125
+
126
+ ### OssClientConfig
127
+
128
+ ```python
129
+ config = OssClientConfig(
130
+ bucket="my-bucket",
131
+ region="cn-hangzhou",
132
+ access_key_id="your-key-id", # 可选,不传走环境变量
133
+ access_key_secret="your-key-secret",
134
+ endpoint=None, # 自定义 Endpoint
135
+ public_base_url=None, # 自定义域名
136
+ use_internal_endpoint=False, # 内网 Endpoint
137
+ multipart_threshold=100 * 1024 * 1024, # 100MB 分片阈值
138
+ part_size=10 * 1024 * 1024, # 10MB 分片大小
139
+ part_parallel=3, # 分片并发数
140
+ )
141
+ ```
142
+
143
+ ### 环境变量
144
+
145
+ ```
146
+ OSS_ACCESS_KEY_ID=your_access_key_id
147
+ OSS_ACCESS_KEY_SECRET=your_access_key_secret
148
+ OSS_REGION=cn-hangzhou
149
+ OSS_BUCKET=my-bucket
150
+ OSS_ENDPOINT=
151
+ OSS_PUBLIC_BASE_URL=
152
+ OSS_USE_INTERNAL_ENDPOINT=false
153
+ ```
154
+
155
+ ## API 参考
156
+
157
+ ### OssClient
158
+
159
+ | 方法 | 说明 |
160
+ |------|------|
161
+ | `upload_file(local_path, object_key, ...)` | 同步上传 |
162
+ | `async_upload_file(local_path, object_key, ...)` | 异步上传 |
163
+ | `object_exists(object_key)` | 同步检查存在 |
164
+ | `async_object_exists(object_key)` | 异步检查存在 |
165
+ | `close()` | 同步关闭 |
166
+ | `async_aclose()` | 异步关闭 |
167
+
168
+ ### UploadResult
169
+
170
+ | 字段 | 类型 | 说明 |
171
+ |------|------|------|
172
+ | `provider` | `str` | 云厂商标识 |
173
+ | `object_key` | `str` | OSS 对象键 |
174
+ | `url` | `str` | 公开访问 URL |
175
+ | `bytes` | `int` | 文件大小 |
176
+ | `etag` | `str | None` | OSS ETag |
177
+ | `skipped` | `bool` | 是否跳过上传 |
178
+
179
+ ## 开发
180
+
181
+ ```bash
182
+ # 同步依赖
183
+ uv sync --all-extras
184
+
185
+ # 运行测试(单元测试)
186
+ uv run pytest
187
+
188
+ # 真实上传测试(需配置环境变量)
189
+ uv run python tests/test_real_upload.py
190
+
191
+ # 代码检查
192
+ uv run ruff check src
193
+ uv run ruff format src
194
+ ```
195
+
196
+ ## License
197
+
198
+ MIT
@@ -0,0 +1,173 @@
1
+ # aod-oss-client
2
+
3
+ 阿里云 OSS 上传客户端,同时支持 **同步** 和 **异步** 两种接口。
4
+
5
+ ## 特性
6
+
7
+ - 同步 + 异步双 API,同一 `OssClient` 实例可多次复用
8
+ - 自动选择简单上传(< 100MB)或分片上传(≥ 100MB)
9
+ - 分片并发上传,内置指数退避重试
10
+ - `content_type` 自动检测,不传自动推断
11
+ - `skip_if_exists` 支持幂等跳过
12
+ - 凭证支持显式传入 / 环境变量 / `.env` 文件
13
+ - 支持自定义域名、内网 Endpoint
14
+
15
+ ## 安装
16
+
17
+ ```bash
18
+ pip install aod-oss-client
19
+ # 或
20
+ uv add aod-oss-client
21
+ ```
22
+
23
+ ## 快速开始
24
+
25
+ ### 同步用法
26
+
27
+ ```python
28
+ from aod_oss_client import OssClient, OssClientConfig
29
+
30
+ config = OssClientConfig(bucket="my-bucket", region="cn-hangzhou")
31
+ client = OssClient(config)
32
+
33
+ r1 = client.upload_file("/data/a.geojson", "data/a.geojson")
34
+ r2 = client.upload_file("/data/b.fgb", "data/b.fgb")
35
+
36
+ print(r1.url, r2.url)
37
+ # client.close() # 可选
38
+ ```
39
+
40
+ ### 异步用法
41
+
42
+ ```python
43
+ from aod_oss_client import OssClient, OssClientConfig
44
+
45
+ config = OssClientConfig(bucket="my-bucket", region="cn-hangzhou")
46
+ client = OssClient(config)
47
+
48
+ r1 = await client.async_upload_file("/data/a.geojson", "data/a.geojson")
49
+ r2 = await client.async_upload_file("/data/b.fgb", "data/b.fgb")
50
+
51
+ print(r1.url, r2.url)
52
+ # await client.async_aclose() # 可选
53
+ ```
54
+
55
+ ### 幂等跳过
56
+
57
+ ```python
58
+ result = client.upload_file("photo.jpg", "images/photo.jpg", skip_if_exists=True)
59
+ if result.skipped:
60
+ print("文件已存在,跳过上传")
61
+ ```
62
+
63
+ ### 自定义元属性
64
+
65
+ 上传时可通过 `metadata` 参数设置 OSS 对象自定义元属性(即 `x-oss-meta-*` 头):
66
+
67
+ ```python
68
+ client.upload_file(
69
+ "data.geojson", "data.geojson",
70
+ metadata={
71
+ "source": "gps_collector",
72
+ "crs": "EPSG:4326",
73
+ "version": "2.1",
74
+ },
75
+ )
76
+ ```
77
+
78
+ 元属性会在 OSS 控制台和 GetObject 响应的 `x-oss-meta-*` 头中返回。
79
+
80
+ ### content_type 自动检测
81
+
82
+ 不传则根据文件扩展名自动推断:
83
+
84
+ ```python
85
+ client.upload_file("data.json", "data.json") # → application/json
86
+ client.upload_file("data.geojson", "data.geojson") # → application/geo+json
87
+ client.upload_file("data.bin", "data.bin") # → application/octet-stream
88
+ client.upload_file("data.fgb", "data.fgb", content_type="application/geo+json") # 手动指定
89
+ ```
90
+
91
+ ### with 语句
92
+
93
+ ```python
94
+ with OssClient(config) as client:
95
+ client.upload_file("a.txt", "a.txt")
96
+ client.upload_file("b.txt", "b.txt")
97
+ ```
98
+
99
+ ## 配置
100
+
101
+ ### OssClientConfig
102
+
103
+ ```python
104
+ config = OssClientConfig(
105
+ bucket="my-bucket",
106
+ region="cn-hangzhou",
107
+ access_key_id="your-key-id", # 可选,不传走环境变量
108
+ access_key_secret="your-key-secret",
109
+ endpoint=None, # 自定义 Endpoint
110
+ public_base_url=None, # 自定义域名
111
+ use_internal_endpoint=False, # 内网 Endpoint
112
+ multipart_threshold=100 * 1024 * 1024, # 100MB 分片阈值
113
+ part_size=10 * 1024 * 1024, # 10MB 分片大小
114
+ part_parallel=3, # 分片并发数
115
+ )
116
+ ```
117
+
118
+ ### 环境变量
119
+
120
+ ```
121
+ OSS_ACCESS_KEY_ID=your_access_key_id
122
+ OSS_ACCESS_KEY_SECRET=your_access_key_secret
123
+ OSS_REGION=cn-hangzhou
124
+ OSS_BUCKET=my-bucket
125
+ OSS_ENDPOINT=
126
+ OSS_PUBLIC_BASE_URL=
127
+ OSS_USE_INTERNAL_ENDPOINT=false
128
+ ```
129
+
130
+ ## API 参考
131
+
132
+ ### OssClient
133
+
134
+ | 方法 | 说明 |
135
+ |------|------|
136
+ | `upload_file(local_path, object_key, ...)` | 同步上传 |
137
+ | `async_upload_file(local_path, object_key, ...)` | 异步上传 |
138
+ | `object_exists(object_key)` | 同步检查存在 |
139
+ | `async_object_exists(object_key)` | 异步检查存在 |
140
+ | `close()` | 同步关闭 |
141
+ | `async_aclose()` | 异步关闭 |
142
+
143
+ ### UploadResult
144
+
145
+ | 字段 | 类型 | 说明 |
146
+ |------|------|------|
147
+ | `provider` | `str` | 云厂商标识 |
148
+ | `object_key` | `str` | OSS 对象键 |
149
+ | `url` | `str` | 公开访问 URL |
150
+ | `bytes` | `int` | 文件大小 |
151
+ | `etag` | `str | None` | OSS ETag |
152
+ | `skipped` | `bool` | 是否跳过上传 |
153
+
154
+ ## 开发
155
+
156
+ ```bash
157
+ # 同步依赖
158
+ uv sync --all-extras
159
+
160
+ # 运行测试(单元测试)
161
+ uv run pytest
162
+
163
+ # 真实上传测试(需配置环境变量)
164
+ uv run python tests/test_real_upload.py
165
+
166
+ # 代码检查
167
+ uv run ruff check src
168
+ uv run ruff format src
169
+ ```
170
+
171
+ ## License
172
+
173
+ MIT