Files
SKYMirror 7f060dd0e4 26.9(安全审计修复版)
Go 1.27.1 (Gin+GORM) + Vue 3 文件快传服务:

- 安全审计全部修复(docs/security-audit-2026-09-05.md):
  bcrypt 密码哈希与自动升级、presign 直传服务端大小/内容校验、
  全局请求体上限、依赖升级(govulncheck 0 命中)、janitor 后台清理、
  管理端审计动作落库、/admin CORS 收紧、通知内容白名单净化、
  会话默认 7 天、限流缓存故障降级、robots.txt 端点等
- 前端:取件链接复制修复(不再重复拼接提取码)、markdown 净化器加固
- Redis 支持库号(FCB_REDIS_DB / redis://…/db URL)
- 文档:docs/api/* 与 openapi.yaml 同步最新行为(robots.txt、
  提码 5 位起、chunk 32MiB 上限、admin 审计动作等)

验证:gofmt/go vet/go test 全绿;二进制端到端冒烟通过
2026-09-05 04:22:41 +08:00

174 lines
4.6 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.
# 分享查询与取件
查询分享元信息(不消耗次数)与真正取件(消耗次数)的完整接口。
`metadata` 每次 423 限流计数外,取件失败还会计入 `error` 限流。
## 元信息:GET /share/metadata
按取件码查询元信息,**不消耗次数**。每次访问即计入 `metadata` 限流。
**参数**`code`query,必需)。
```bash
curl -s "http://localhost:8466/share/metadata?code=K3P9W"
```
**成功响应**200):
```json
{
"code": 200, "msg": "ok",
"data": {
"code": "K3P9W",
"name": "report.pdf",
"size": 1048576,
"type": "file",
"is_text": false,
"created_at": "2025-06-01T12:00:00+08:00",
"expired_at": "2025-06-08T12:00:00+08:00",
"expires_at": "2025-06-08T12:00:00+08:00",
"expired_count": -1,
"used_count": 3,
"remaining_downloads": null
}
}
```
字段说明:
| 字段 | 说明 |
|---|---|
| `type` | `text`(文本分享)/ `file`(文件分享) |
| `is_text` | 是否文本分享 |
| `size` | 字节数 |
| `expired_at` / `expires_at` | 过期时间(RFC 3339);永久分享为 `null` |
| `expired_count` | `-1` 按时间/永久;`>0` 剩余可取次数(原始限额) |
| `used_count` | 已取次数 |
| `remaining_downloads` | 剩余可取次数(仅次数型分享有值,否则 `null` |
> 不返回存储路径等敏感字段。
**错误响应**
```json
{ "code": 404, "msg": "文件不存在" }
```
```json
{ "code": 404, "msg": "文件已过期" }
```
## 元信息(POST):POST /share/metadata
等价的 JSON 版本(`code` 放请求体):
```bash
curl -s -X POST http://localhost:8466/share/metadata \
-H 'Content-Type: application/json' \
-d '{"code":"K3P9W"}'
```
响应与 GET 版本一致。
## 取件(消耗次数):GET /share/select
**每调用一次消耗 1 次取件**(次数型分享扣减 `expired_count`;时间型扣减不计)。
- 文本分享:返回 `text/plain; charset=utf-8` 正文(非 JSON 封装),`Content-Disposition` 携带文件名。
- 文件分享:返回文件流(`200` 全量 / `206` 区间),支持 `Range`
```bash
curl -s -OJ "http://localhost:8466/share/select?code=K3P9W"
```
次数耗尽或已过期:
```json
{ "code": 404, "msg": "文件已过期" }
```
超限(计入 error 限流):
```json
{ "code": 423, "msg": "请求次数过多,请稍后再试" }
```
## 取件详情:POST /share/select
返回元信息 + 文本内容/下载地址的 JSON 详情。**消耗语义**:次数型分享(`expired_count >= 0`
返回代理地址 `download_url` 且本次**不消耗**(消耗发生在访问代理地址时);时间型/永久/文本分享在本次消耗。
```bash
curl -s -X POST http://localhost:8466/share/select \
-H 'Content-Type: application/json' \
-d '{"code":"K3P9W"}'
```
**文件分享响应**200):
```json
{
"code": 200, "msg": "ok",
"data": {
"code": "K3P9W",
"name": "report.pdf",
"size": 1048576,
"type": "file",
"is_text": false,
"created_at": "2025-06-01T12:00:00+08:00",
"expired_at": "2025-06-08T12:00:00+08:00",
"expires_at": "2025-06-08T12:00:00+08:00",
"expired_count": -1,
"used_count": 4,
"remaining_downloads": null,
"text": "/share/download?key=9f2c…&code=K3P9W",
"download_url": "/share/download?key=9f2c…&code=K3P9W"
}
}
```
> S3 引擎下时间型/永久分享的 `download_url` 可能是预签名直链(1 小时有效)而非代理地址;
> 次数型分享恒为代理地址 `"/share/download?key=…&code=…"`。
**文本分享响应**200):
```json
{
"code": 200, "msg": "ok",
"data": {
"code": "8XQ2M", "name": "Text.txt", "size": 24, "type": "text", "is_text": true,
"created_at": "2025-06-01T12:00:00+08:00",
"expired_at": "2025-06-02T12:00:00+08:00", "expires_at": "2025-06-02T12:00:00+08:00",
"expired_count": -1, "used_count": 1, "remaining_downloads": null,
"text": "你好,文件快传",
"content": "你好,文件快传",
"download_url": null
}
}
```
## 代理下载:GET /share/download
`POST /share/select` 返回的代理地址,**每次访问消耗 1 次**,支持 Range。
| 参数 | 说明 |
|---|---|
| `key` | 窗口令牌(服务端下发,双窗口校验) |
| `code` | 取件码 |
```bash
curl -s -OJ "http://localhost:8466/share/download?key=9f2c…&code=K3P9W"
```
**错误响应**
```json
{ "code": 403, "msg": "下载鉴权失败" }
```
```json
{ "code": 404, "msg": "文件已过期" }
```
> `key` 鉴权失败会计入 error 限流;文本分享经该接口返回 JSON 封装 `data` 为文本内容。