- 完整 skill 本体:SKILL.md / README.md / manifest.json / config.json - scripts/123yunpan.py:零依赖 CLI(含空间双配额、QPS 限流、零依赖 XLSX) - references/ 参考资料 - 排除 .workbuddy/ 开发目录与 __pycache__
125 lines
4.9 KiB
Markdown
125 lines
4.9 KiB
Markdown
# 123云盘上传模式 & 竞品分析
|
||
|
||
> 来源:分析 Skillhub 上 `123pan-upload` skill 的实现,提取可借鉴的模式。
|
||
|
||
## 短直链生成(Short Direct Link)
|
||
|
||
直链 URL 包含 user_id 和文件路径,较长且暴露用户信息。短直链只用 file_id,更隐私友好:
|
||
|
||
```python
|
||
import base64, json
|
||
|
||
def get_user_id_from_token(token: str) -> int:
|
||
"""从 JWT token 解析 user_id,无需额外 API 调用"""
|
||
parts = token.split(".")
|
||
if len(parts) >= 2:
|
||
payload = parts[1]
|
||
padding = 4 - len(payload) % 4
|
||
if padding != 4:
|
||
payload += "=" * padding
|
||
data = json.loads(base64.b64decode(payload))
|
||
return data.get("id", 0)
|
||
return 0
|
||
|
||
def get_short_direct_link(user_id: int, file_id: int) -> str:
|
||
return f"https://{user_id}.v.123pan.cn/{user_id}/{file_id}"
|
||
```
|
||
|
||
**对比:**
|
||
| 类型 | URL 格式 | 隐私性 | 可直链下载 |
|
||
|------|---------|--------|-----------|
|
||
| 分享链接 | `https://www.123pan.com/s/{shareKey}` | ✅ 好 | ❌ 需跳转 |
|
||
| 完整直链 | `https://{user_id}.v.123pan.cn/{user_id}/{file_id}/{filename}` | ⚠️ 暴露路径 | ✅ |
|
||
| 短直链 | `https://{user_id}.v.123pan.cn/{user_id}/{file_id}` | ⚠️ 暴露 user_id | ✅ |
|
||
|
||
## 上传流程(V2 API)
|
||
|
||
> ⚠️ **2026-05 验证**:以下流程经过实际 API 调用验证,修正了早期文档中的错误。
|
||
|
||
### 两个域名
|
||
|
||
| 域名 | 用途 | 端点 |
|
||
|------|------|------|
|
||
| `https://open-api.123pan.com` | 主 API(认证、文件管理、chunked create) | `/api/v1/*`, `/api/v2/*`, `/upload/v2/file/create` |
|
||
| `https://openapi-upload.123242.com` | 上传专用(获取上传域名返回此值) | `/upload/v2/file/single/create`, `/upload/v2/file/slice`, `/upload/v2/file/upload_complete` |
|
||
|
||
获取上传域名:`GET /upload/v2/file/domain` → 返回 `["https://openapi-upload.123242.com"]`(列表,非对象)
|
||
|
||
### 单文件上传(<100MB)
|
||
|
||
```
|
||
1. GET open-api.123pan.com/upload/v2/file/domain → 获取上传服务器地址
|
||
2. POST openapi-upload.123242.com/upload/v2/file/single/create → multipart/form-data 上传
|
||
```
|
||
|
||
**关键坑点**:
|
||
- `single/create` **必须用 multipart/form-data**,不能用 JSON body。JSON 会导致 500 服务器崩溃。
|
||
- 表单字段:`parentFileID`(text), `filename`(text), `etag`(text), `size`(text), `file`(file)
|
||
- `duplicate` 字段:**不要传 `0`**(会导致 "duplicate参数错误")。不传默认覆盖,或传 `1`(重命名)/`2`(覆盖)。
|
||
- 响应:`{"code":0, "data":{"fileID": 12345, "completed": true}}` — 无需额外上传步骤。
|
||
|
||
### 分片上传(100MB-10GB)
|
||
|
||
```
|
||
1. POST open-api.123pan.com/upload/v2/file/create → 创建上传任务(主域名)
|
||
2. POST openapi-upload.123242.com/upload/v2/file/slice → 逐片上传(上传域名)
|
||
3. POST openapi-upload.123242.com/upload/v2/file/upload_complete → 完成上传(上传域名)
|
||
```
|
||
|
||
**关键坑点**:
|
||
- `create` 调用主 API 域名,不是上传域名!
|
||
- `slice` 和 `upload_complete` 调用上传域名。
|
||
- `slice` 请求体字段名为 `partMd5`(注意:不是 `sliceMD5`,后者会导致 500)。
|
||
- 分片大小由 `create` 响应中的 `sliceSize` 决定(通常 16MB)。
|
||
|
||
### SHA1 秒传
|
||
```python
|
||
# create_file 响应中 reuse=true 表示文件已存在,跳过上传
|
||
if create_result["reuse"]:
|
||
return {"file_id": create_result["file_id"], ...}
|
||
```
|
||
|
||
### 上传校验轮询
|
||
```python
|
||
# upload_complete 响应中 completed=false 时需轮询
|
||
# 建议间隔:1 秒
|
||
# 最大等待:~5 分钟/GB(10GB 文件约 50 分钟)
|
||
# 文件大小越大,校验时间越长
|
||
for attempt in range(max_retries):
|
||
resp = api_post("/upload/v2/file/upload_complete", {"preuploadID": preupload_id})
|
||
if resp["data"].get("completed"):
|
||
return resp["data"] # 校验完成
|
||
time.sleep(1) # 按 API 文档要求,每秒轮询一次
|
||
```
|
||
|
||
### MD5 作为 Etag
|
||
上传创建时需要提供文件的 MD5 作为 `etag` 字段:
|
||
```python
|
||
import hashlib
|
||
etag = hashlib.md5(open(file_path, "rb").read()).hexdigest()
|
||
```
|
||
|
||
## WebDAV 上传(>10GB 文件)
|
||
|
||
API 上传上限 10GB,超大文件可用 WebDAV + rclone:
|
||
|
||
```bash
|
||
# 1. 配置 rclone(隔离配置,避免读取其他云服务凭证)
|
||
rclone config --config ~/123pan-rclone.conf
|
||
# 添加 "123pan-webdav" remote
|
||
|
||
# 2. 上传
|
||
RCLONE_CONFIG=~/123pan-rclone.conf rclone copy /path/to/large/file 123pan-webdav:/folder -P
|
||
|
||
# 3. 上传后通过 API 查找文件(WebDAV 上传有 30-90 秒索引延迟)
|
||
# 需要轮询 file/list 接口等待文件出现
|
||
```
|
||
|
||
**注意:** WebDAV 上传后文件不会立即出现在 API 列表中,需要重试查找(最多 30 次,每次间隔 3 秒)。
|
||
|
||
## 安全实践
|
||
|
||
- rclone 配置隔离:用 `RCLONE_CONFIG` 环境变量指定独立配置文件
|
||
- 凭证存储:用环境变量或 `.env` 文件,不要硬编码
|
||
- Token 刷新:123yunpan.py CLI 已自动处理 401 响应时的 token 刷新
|