Files
hi-server/doc/tapi-file-upload-zh.md
shanshanzhong147 0d57450283
Build docker and publish / build (20.15.1) (push) Has been cancelled
x
2026-05-15 09:53:15 -07:00

185 lines
4.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# TAPI 文件上传接入说明
本文档说明 `https://tapi.hifast.biz/v1/public/file/upload` 相关上传接口的推荐接入方式、签名规则与常见排查方式。
## 总览
上传能力包含两类接入方式:
- 推荐方式:`init -> S3 PUT -> complete`
- 兼容方式:`/upload` multipart 直传
推荐优先使用预签名三段式,因为:
- 现有签名串包含 `BODY_SHA256`
- `/upload``multipart/form-data`
- multipart 原始 body 的签名和调试成本更高
- `init``complete` 是 JSON,更适合客户端和 Apifox 调试
## 签名生效逻辑
项目保持现有旧逻辑,不做强制签名改造:
- `Signature.EnableSignature = false` 时:不校验签名
- `Signature.EnableSignature = true` 且未携带 `X-App-Id` 时:不校验签名,兼容老客户端
- `Signature.EnableSignature = true` 且携带 `X-App-Id` 时:必须同时携带并校验
- `X-Timestamp`
- `X-Nonce`
- `X-Signature`
这意味着:
- 新客户端建议始终带完整签名头
- 老客户端如果没有 `X-App-Id`,仍可按旧逻辑访问
## 签名头定义
- `X-App-Id`: 客户端标识,例如 `ios-client`
- `X-Timestamp`: Unix 秒级时间戳
- `X-Nonce`: 每次请求唯一随机串
- `X-Signature`: `HMAC-SHA256` 结果的十六进制小写字符串
## StringToSign 规则
StringToSign 由下面 7 段按换行符 `\n` 拼接:
```text
METHOD
PATH
CANONICAL_QUERY
BODY_SHA256
X-App-Id
X-Timestamp
X-Nonce
```
说明:
- `METHOD`HTTP 方法大写,例如 `POST`
- `PATH`:请求路径,例如 `/v1/public/file/upload/init`
- `CANONICAL_QUERY`:按 key 排序后的 query string,没有 query 则为空字符串
- `BODY_SHA256`:请求体原始字节的 SHA-256 十六进制小写
- 其余三项直接使用请求头值
签名计算方式:
```text
signature = hex_lower(HMAC_SHA256(app_secret, string_to_sign))
```
时间窗与防重放:
- `X-Timestamp` 默认有效时间窗是 300 秒
- `X-Nonce` 在有效时间窗内不能重复使用
## 推荐接入:预签名三段式
### 1. 初始化上传
请求:
```bash
curl -X POST 'https://tapi.hifast.biz/v1/public/file/upload/init' \
-H 'Accept: application/json, text/plain, */*' \
-H 'Content-Type: application/json' \
-H 'authorization: your-token' \
-H 'X-App-Id: ios-client' \
-H 'X-Timestamp: 1778776400' \
-H 'X-Nonce: nonce-001' \
-H 'X-Signature: your-signature' \
-d '{
"biz_type": "app-package",
"file_name": "demo.zip",
"content_type": "application/zip",
"size": 123456,
"sha256": ""
}'
```
典型返回:
```json
{
"code": 200,
"msg": "success",
"data": {
"file_id": "c29274ee26ab5aa211e0396e",
"object_key": "app-upload/app-package/519/2026/05/c29274ee26ab5aa211e0396e_demo.zip",
"upload_url": "https://bucket.s3.ap-east-1.amazonaws.com/...",
"method": "PUT",
"headers": {
"Content-Type": "application/zip"
},
"expired_at": 1778776715
}
}
```
### 2. 直传 S3
这一步是直接上传二进制文件到 S3,不走业务签名中间件。
```bash
curl -X PUT 'https://bucket.s3.ap-east-1.amazonaws.com/...' \
-H 'Content-Type: application/zip' \
--upload-file '/tmp/demo.zip'
```
说明:
- `Content-Type` 需和 `init` 返回的 `headers.Content-Type` 一致
- `upload_url` 有过期时间,通常 300 秒
- 成功时 S3 常见返回 `200``204`
### 3. 完成上传
```bash
curl -X POST 'https://tapi.hifast.biz/v1/public/file/upload/complete' \
-H 'Accept: application/json, text/plain, */*' \
-H 'Content-Type: application/json' \
-H 'authorization: your-token' \
-H 'X-App-Id: ios-client' \
-H 'X-Timestamp: 1778776405' \
-H 'X-Nonce: nonce-002' \
-H 'X-Signature: your-signature' \
-d '{
"file_id": "c29274ee26ab5aa211e0396e"
}'
```
## 兼容接入:单接口 multipart 直传
接口:
- `POST /v1/public/file/upload`
表单字段:
- `biz_type`
- `file`
说明:
- 该接口继续保留,兼容旧客户端
- 如果请求带了 `X-App-Id`,就按现有逻辑验签
- 如果没有 `X-App-Id`,仍按旧逻辑放行
- 如果要给该接口加签,签名时必须对原始 multipart body 计算 `BODY_SHA256`
## 常见错误码
- `200`: 成功
- `400`: 参数错误
- `40008`: 缺少签名头
- `40009`: 签名已过期
- `40010`: 签名无效
- `40011`: nonce 重放
- `10001`: 上传元数据不存在或对象不存在
## 排查建议
- `40008`:确认带了 `X-App-Id` 后,也同时带上 `X-Timestamp / X-Nonce / X-Signature`
- `40009`:检查客户端时间是否偏差过大
- `40010`:确认 `PATH`、query 排序、body 原始字节、secret 是否完全一致
- `40011`:确保每次请求都生成新的 `X-Nonce`
- `complete` 失败:确认 S3 `PUT` 已成功,且上传大小与 `init.size` 一致