- 全项目版本号统一:v3.x 迭代号(26.9/26.9/26.9/26.9 及裸 v2/v3)→ 26.9, 覆盖 Go 注释 / 文档 / openapi.yaml / README×4 / 前端源码(80+ 处) - v31_test.go 更名 custom_code_test.go;TestV2AccessorDefaults → TestKVAccessorDefaults - docs/api/00-overview.md 更新日志合并为单条 26.9 条目(修复错位拼接) - .goreleaser.yaml 头部注释与实际一致(Pro 2.18.1 / GITEA_TOKEN / semver tag 要求) - CI:release-image.yml → ci.yml,仅保留 vet+test 门禁; 镜像发布移交 GoReleaser Pro(原 build-push 的 tag 校验与 26.9 版本方案冲突,历史 9 次失败) - 前端重建:server/web/dist 与 web-embed 同步(docs 文案嵌入更新)
6.2 KiB
存储引擎配置
存储引擎只支持三种:本地磁盘 / S3 / WebDAV,由进程级环境变量 FCB_STORAGE_ENGINE 选择。
引擎与引擎相关配置在启动时一次性读取(storage.SetEngineOptions → NewEngine),
运行时修改引擎 KV 需重启服务(管理端 GET /admin/config/get 的 _engine_hint 亦有提示)。
引擎选择
FCB_STORAGE_ENGINE=local # 启动默认(KV storage_engine 为空时生效)
FCB_STORAGE_ENGINE=s3
FCB_STORAGE_ENGINE=webdav
非法值直接启动失败:FCB_STORAGE_ENGINE 无效值 "xxx",仅支持 local|s3|webdav。
26.9 运行时热切换:管理端 POST /admin/storage/switch(或后台设置页「存储引擎」卡)可在不重启的情况下切换引擎——
先构建新引擎并健康检查,通过才生效;失败 503 保持原引擎。当前引擎持久化在 settings KV storage_engine(空=回落启动值)。
各引擎参数(存储目录/服务地址/存储桶/密钥)同样在后台设置页运行时可改;保存后对应引擎实例缓存失效,下次切换/构建生效。
文件归属引擎(26.9)
每条分享记录(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 + Digest(RFC 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:
{ "code": 501, "msg": "当前存储引擎不支持该操作" }
Docker Compose 冒烟编排
deploy/docker-compose.yml 提供可选 profile(详见 deploy/README.md):
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:存储空间已达到管理员设置的容量上限。