Files
FileShare/docs/api/09-storage.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

120 lines
6.2 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.
# 存储引擎配置
存储引擎只支持三种:**本地磁盘 / S3 / WebDAV**,由进程级环境变量 `FCB_STORAGE_ENGINE` 选择。
引擎与引擎相关配置在启动时一次性读取(`storage.SetEngineOptions``NewEngine`),
**运行时修改引擎 KV 需重启服务**(管理端 `GET /admin/config/get``_engine_hint` 亦有提示)。
## 引擎选择
```bash
FCB_STORAGE_ENGINE=local # 启动默认(KV storage_engine 为空时生效)
FCB_STORAGE_ENGINE=s3
FCB_STORAGE_ENGINE=webdav
```
非法值直接启动失败:`FCB_STORAGE_ENGINE 无效值 "xxx",仅支持 local|s3|webdav`
**v3 运行时热切换**:管理端 `POST /admin/storage/switch`(或后台设置页「存储引擎」卡)可在不重启的情况下切换引擎——
先构建新引擎并健康检查,通过才生效;失败 503 保持原引擎。当前引擎持久化在 settings KV `storage_engine`(空=回落启动值)。
各引擎参数(存储目录/服务地址/存储桶/密钥)同样在后台设置页运行时可改;保存后对应引擎实例缓存失效,下次切换/构建生效。
## 文件归属引擎(v3
每条分享记录(`file_codes.engine`)与上传会话(`upload_chunks.engine` / `presign_upload_sessions.engine`
在创建时戳记当时的引擎名。下载、分片合并、删除按**归属引擎**操作——切换引擎后,旧引擎里的文件仍可正常下载与删除
(空戳为历史数据,回落当前引擎)。
## 按日期目录存储
文件落盘路径:`[storage_path/]share/data/YYYY/MM/DD/<uuid>/<文件名>`(如 `share/data/2026/09/04/…`)。
按日嵌套目录自然排序、无日月歧义、避免单日海量文件挤在单目录;三种引擎一致适用;历史路径记录在
`file_codes.file_path`,不受路径规则调整影响。
## 配置键与环境变量
引擎相关配置键(DB settings KV)可由环境变量种子注入(优先级:默认 < 环境变量 < DB KV):
| KV 键 | 环境变量 | 引擎 | 说明 |
|---|---|---|---|
| `local_storage_path` | `FCB_LOCAL_STORAGE_PATH` | local | 本地存储根目录(容器内默认 `/app/data` |
| `storage_path` | `FCB_STORAGE_PATH` | 全部 | 存储相对路径前缀(空 = `share/data/…` |
| `s3_access_key_id` | `FCB_S3_ACCESS_KEY_ID` | s3 | 访问密钥 |
| `s3_secret_access_key` | `FCB_S3_SECRET_ACCESS_KEY` | s3 | 私有密钥 |
| `aws_session_token` | `FCB_AWS_SESSION_TOKEN` | s3 | 可选临时会话令牌 |
| `s3_bucket_name` | `FCB_S3_BUCKET_NAME` | s3 | 桶名 |
| `s3_endpoint_url` | `FCB_S3_ENDPOINT_URL` | s3 | S3 兼容端点(MinIO/R2 等;AWS 原生可空) |
| `s3_region_name` | `FCB_S3_REGION_NAME` | s3 | 区域(默认 `auto` |
| `s3_addressing_style` | `FCB_S3_ADDRESSING_STYLE` | s3 | `auto`/`path`/`virtual` |
| `webdav_url` | `FCB_WEBDAV_URL` | webdav | WebDAV 服务地址(如 `http://webdav:5000` |
| `webdav_username` | `FCB_WEBDAV_USERNAME` | webdav | 用户名 |
| `webdav_password` | `FCB_WEBDAV_PASSWORD` | webdav | 密码 |
| `webdav_root_path` | `FCB_WEBDAV_ROOT_PATH` | webdav | 根目录(默认 `filebox_storage`,不存在自动逐级创建) |
`FCB_STORAGE_ENGINE` 本身不落库(`GET /admin/config/get` 中的 `file_storage` 为 KV 记忆键,
进程实际引擎以 `FCB_STORAGE_ENGINE``_engine_hint.storage_backend` 为准)。
## 各引擎要点
### 本地引擎(local
- 原子写:临时文件 + fsync + rename,避免半写文件。
- 路径安全:`SanitizePath` + 符号链接逃逸双重防穿越。
- Range 下载基于 `SectionReader`;分片按索引有序合并 + SHA256 校验,合并后清理分片目录。
### S3 引擎(s3
- 原生 multipart 流式合并(失败自动 Abort),分片落临时文件保证精确 Content-Length 与可重放。
- 预签名 GET/PUT 直链(预签名直传唯一 `direct` 模式引擎)。
- SDK 内置 5xx 指数退避重试;`when_required` 校验模式兼容 MinIO/R2 与纯流式转发。
### WebDAV 引擎(webdav,重点优化)
- **连接复用**:池化 Transport,连接复用(实测 25 次请求仅 1 条 TCP 连接)。
- **认证**Basic + DigestRFC 2617 `qop=auth`MD5/SHA-256)自动协商,401 挑战驱动。
- **Range**`Range` 头透传 + `206` 解析,支持分块/断点下载。
- **重试**5xx/429/408 指数退避(封顶 2s ± 20% 抖动,尊重 `Retry-After`)。
- **流式**:下载经 `io.Pipe` 流式转发不落盘;上下文取消挂到响应体读完之后,防止提前断连。
- **目录**:按需逐级 `MKCOL` + 目录缓存,避免重复建目录。
- **超时**:可配置(`webdav_url` 同级暂无独立超时键,引擎默认值内置)。
## 健康检查
三引擎均实现 `HealthCheck`local 写探针、s3 `ListObjectsV2`、webdav `PROPFIND`(根目录不存在时自建)。
服务启动时预检失败仅告警不阻断;运行状态可经 `GET /api/v1/health``data.storage` 查看当前引擎名。
## 预签名直传支持矩阵
| 引擎 | `PresignPutURL` / `PresignGetURL` | init 返回 mode |
|---|---|---|
| s3 | ✅ | `direct` |
| local / webdav | ❌(`ErrNotSupported` | `proxy`(走服务端代理上传) |
引擎不支持的操作经统一映射返回 501:
```json
{ "code": 501, "msg": "当前存储引擎不支持该操作" }
```
## Docker Compose 冒烟编排
`deploy/docker-compose.yml` 提供可选 profile(详见 deploy/README.md):
```bash
docker compose --profile minio up -d --build # MinIO(含 mc 自动建桶)+ FCB_STORAGE_ENGINE=s3
docker compose --profile webdav up -d --build # dufs WebDAV 冒烟(admin/admin123+ FCB_STORAGE_ENGINE=webdav
docker compose --profile redis up -d --build # Redis 缓存增强(非引擎)
```
## 存储哨兵错误 → HTTP 状态
| 哨兵错误 | HTTP | 文案 |
|---|---|---|
| `ErrNotFound` | 404 | 文件不存在 |
| `ErrInvalidPath` | 400 | 非法文件路径 |
| `ErrUnavailable` | 503 | 存储服务不可用,请稍后再试 |
| `ErrNotSupported` | 501 | 当前存储引擎不支持该操作 |
| `ErrRangeNotSatisfiable` | 416 | 请求范围超出文件大小 |
| `ErrHashMismatch` | 400 | 分片哈希校验失败,请重新上传 |
容量超限(`storageLimit`,经容量预留判定)返回 507`存储空间已达到管理员设置的容量上限`