Files
FileShare/docs/api/03-file-share.md
T
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

104 lines
3.3 KiB
Markdown
Raw 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.
# 文件分享
上传单个文件并创建分享。支持扩展名/MIME 白名单 + **magic bytes 防伪**(读文件前 64 字节校验,
伪造类型返回 403)。经审计中间件落库(action=upload,记录文件总大小与实际传输字节)。
## POST /share/file
**请求参数**`multipart/form-data`):
| 参数 | 类型 | 必需 | 默认 | 说明 |
|---|---|---|---|---|
| `code` | string,可选;自定义提取码,5-8 位字母或数字(空=随机生成;占用 400) |
| `file` | file | ✅ | - | 上传的文件(大小 ≤ 生效上限:`max_file_size>0` 时为其,否则 `uploadSize` |
| `expire_value` | int | ❌ | `1` | 过期值(配合 `expire_style``count` 型受 `max_save_count` 约束) |
| `expire_style` | string | ❌ | `day` | `day`/`hour`/`minute`/`count`/`forever`(须在 `expireStyle` 白名单内) |
**curl 示例**
```bash
curl -s -X POST http://localhost:8466/share/file \
-F 'file=@./report.pdf;type=application/pdf' \
-F 'expire_value=7' \
-F 'expire_style=day'
```
**成功响应**200):
```json
{ "code": 200, "msg": "ok", "data": { "code": "K3P9W", "name": "report.pdf" } }
```
**错误响应**
```json
{ "code": 400, "msg": "缺少上传文件 file 字段" }
```
```json
{ "code": 403, "msg": "大小超过限制,最大为10.00 MB" }
```
> 大小上限为动态策略(v2 需求 ④⑩):管理端改 `max_file_size`0=回落 `uploadSize`)后
> **下一次上传立即按新上限执行**,无需重启;上限值可经 `GET /api/v1/config` 的
> `max_file_size`/`maxFileSize` 字段读取。
```json
{ "code": 403, "msg": "不允许上传该类型文件" }
```
```json
{ "code": 403, "msg": "文件内容与扩展名不匹配,疑似伪造类型" }
```
```json
{ "code": 403, "msg": "限制最长时间为 7天,可换用其他方式" }
```
```json
{ "code": 403, "msg": "限制次数最多为 5 次" }
```
```json
{ "code": 403, "msg": "请求次数过多,请稍后再试" }
```
```json
{ "code": 507, "msg": "存储空间已达到管理员设置的容量上限" }
```
```json
{ "code": 503, "msg": "存储服务不可用,请稍后再试" }
```
## 文件类型白名单
由配置 `allowed_file_types` 控制(管理端可改):
- `*`:不限制(默认)。
- 扩展名规则:`.png``pdf`(自动补点)等,按文件名后缀匹配。
- MIME 规则:`image/*``application/pdf` 等,按请求 `Content-Type` 通配匹配。
已知类型(png/jpg/gif/webp/bmp/pdf/zip/rar/7z/gz/mp3/mp4/exe/elf)会做 **magic bytes 交叉校验**
扩展名或 Content-Type 声明了已知类型,但文件头不匹配时拒绝(403「疑似伪造类型」)。
## 下载取件
- `GET /share/select?code=<code>`:消耗 1 次取件,返回文件流(`200` 全量 / `206` 区间,
支持 `Range` 请求头;响应含 `Accept-Ranges: bytes``Content-Disposition: attachment; filename*=UTF-8''...`)。
- `POST /share/select`:返回详情 JSON`download_url` 为代理下载地址(见下)。
- `GET /share/download?key=<token>&code=<code>`:代理下载,消耗 1 次,同样支持 Range。
Range 示例(取前 1024 字节):
```bash
curl -s -H 'Range: bytes=0-1023' -o part.bin \
"http://localhost:8466/share/select?code=K3P9W"
```
区间越界返回:
```json
{ "code": 416, "msg": "请求范围超出文件大小" }
```