- 对象存储直链:S3 引擎 302 到限时预签名 URL(有效期钳位分享剩余时效),失败自动回落代理 - 过期回收:janitor 定时扫描 + 取件惰性回收 + 管理端手动触发(POST /admin/recycle/run), retention_days 最长存储时长;删除走引用计数(去重对象安全) - SHA512 内容去重:三条上传链路落库后计算哈希,命中即复用旧对象并删除本次副本 - 下载防盗链:Referer 白名单(同源/空 Referer/通配域名放行),挂 /share/download - 取件页图片/音频内联预览(下载地址直连,加载失败回退下载按钮) - 文件夹上传:拖拽目录明确提示"建议压缩后上传"(webkitGetAsEntry 探测) - 管理端设置卡「回收与下载安全」8 个新配置键(KVSchema + configKeys + UI + i18n) - 前端产物重建并同步 server/web/dist 与 web-embed - 文档:10-config 配置表、03-file-share 直链/防盗链/文件夹章节、07-admin 回收端点、openapi
13 KiB
环境变量与配置项
配置分三层:默认值 → FCB_* 环境变量 → 数据库 settings KV(管理端运行时修改)。
26.9 起进程必需的环境变量为空集:数据库默认 SQLite(modernc.org/sqlite 纯 Go 驱动,零外部依赖,
DSN 缺省落 ./data/fileshare.db);FCB_DB_DRIVER=postgres 时 FCB_DB_DSN 必需(需求 ⑧)。
环境变量(进程级)
| 变量 | 必需 | 默认 | 说明 |
|---|---|---|---|
FCB_DB_DRIVER |
❌ | sqlite |
数据库驱动:sqlite / postgres(需求 ⑧) |
FCB_DB_DSN |
视驱动 | ./data/fileshare.db |
postgres:连接串(必需,如 postgres://user:pass@host:5432/filecodebox?sslmode=disable);sqlite:数据库文件路径(可空,父目录自动创建) |
FCB_REDIS_ADDR |
❌ | 空 | Redis 地址(如 redis:6379),也支持 redis://[:password@]host:port[/db] / rediss://(TLS)URL 形式;空则缓存降级为进程内存实现(缓存故障时自动降级为进程内限流计数) |
FCB_REDIS_DB |
❌ | 0 |
Redis 逻辑库号 0-15;URL 形式地址显式携带 /N 时以 URL 为准 |
FCB_ADMIN_PASSWORD |
❌ | 空 | 设置后服务首次启动即自动初始化管理员(≥8 位,不足告警跳过),消除 /setup 被抢占窗口;初始化完成后建议移除 |
FCB_LISTEN |
❌ | :8466 |
HTTP 监听地址 |
FCB_STORAGE_ENGINE |
❌ | local |
存储引擎:local / s3 / webdav |
FCB_TRUSTED_PROXIES |
❌ | 空 | 可信代理 CIDR(逗号分隔),命中时从 X-Forwarded-For 解析真实客户端 IP |
- SQLite 连接参数(驱动自动注入):
busy_timeout=10s+WAL日志模式 +foreign_keys=1;连接池 8/4。 - Postgres 连接池沿用 v1 参数(32/8,1h 轮换);
FCB_DB_DRIVER=postgres且未设FCB_DB_DSN时启动直接报错。
引擎相关环境变量(种子注入 settings KV,见《存储引擎配置》):FCB_LOCAL_STORAGE_PATH、
FCB_STORAGE_PATH、FCB_S3_ACCESS_KEY_ID、FCB_S3_SECRET_ACCESS_KEY、FCB_AWS_SESSION_TOKEN、
FCB_S3_BUCKET_NAME、FCB_S3_ENDPOINT_URL、FCB_S3_REGION_NAME、FCB_S3_ADDRESSING_STYLE、
FCB_WEBDAV_URL、FCB_WEBDAV_USERNAME、FCB_WEBDAV_PASSWORD、FCB_WEBDAV_ROOT_PATH。
部署用编排变量(deploy/.env.example):WEB_PORT(默认 8466)、
POSTGRES_USER / POSTGRES_PASSWORD / POSTGRES_DB(默认 fileshare,仅 --profile postgres 时使用)。
配置项(settings KV,默认值对齐参考实现)
键名/类型/默认值/边界以
server/internal/config/schema.go的KVSchema()为单一事实来源 (schema 同步测试保证与 defaults() 逐键一致);26.9 新增键统一 snake_case。
站点信息与展示(需求 ①②③)
| 键 | 类型/边界 | 默认 | 说明 |
|---|---|---|---|
site_name / name |
string | 文件快传 | 站点名称(site_name 优先) |
site_domain |
string,≤256 | 空 | 26.9:站点对外域名(http(s)://host[:port],不带路径;裸主机自动补 http://)。配置后分享链接(结果卡/管理端复制)用该域名生成——内网部署也能把公网链接发出去;留空=用当前访问地址 |
description |
string | 开箱即用的文件快传系统 | 站点描述 |
page_explain |
string | (合规声明) | 页面说明文案 |
keywords |
string | 文件快传, 文件分享… | SEO 关键词 |
logo_url |
string | 空(前端回落本地打包 /assets/logo-*.svg,需求 ⑤) |
页面导航 Logo,管理端可设任意 URL |
favicon_url |
string | 空(前端回落本地打包 /assets/favicon-*.png,需求 ⑤) |
favicon / 备用 Logo |
opacity |
float | 0.9 | 界面不透明度 |
background |
string | 空 | 背景图 URL(参考实现既有键,v1 兼容保留) |
background_url |
string,≤2048 字符 | 空 | 26.9 需求 ①:背景图 URL 或上传后地址(空=主题默认;取值时 legacy background 键兜底)。管理端保存时校验协议白名单:仅 http(s)、data:image/* 与站内相对路径(防 javascript: 注入,非法 400) |
footer_text |
string,≤2000 字符 | 空 | 26.9 需求 ②:页脚自定义内容(纯文本或受控 HTML 片段) |
footer_beian |
string,≤128 字符 | 空 | 26.9 需求 ②:备案号(如 京ICP备2024xxxxxx号-1),展示于页脚 |
notify_enabled |
int(0/1) | 1 | 26.9 需求 ③:通知开关(1=前台右上角悬浮窗展示 / 0=关闭) |
notify_title |
string,≤128 字符 | 系统通知 | 通知标题 |
notify_content |
string,≤2000 字符 | 欢迎使用… | 通知正文(服务端白名单净化:仅保留纯文本与 <a href> 为 http(s)/站内相对/# 锚点的链接,其余标签与事件属性剥离,保存与读取双侧生效) |
showAdminAddr |
int(0/1) | 0 | 是否展示后台入口 |
robotsText |
string | User-agent: *\nDisallow: / |
robots.txt 内容(由公开端点 GET /robots.txt 输出) |
保存策略(需求 ④,上传页动态读取并在范围内选择)
| 键 | 类型/边界 | 默认 | 说明 |
|---|---|---|---|
max_save_seconds |
int64,0~31536000 | 0 | 最长保存秒数上限(0=仅默认 7 天兜底;>0 时按时间过期超限 403「限制最长时间为 X,可换用其他方式」)。26.9:管理界面以「小时/天」下拉单位编辑(≥1 天自动显示天),提交时前端换算为秒——canonical 单位保持秒,接口语义不变 |
max_save_count |
int,0~100000 | 0 | 26.9 新增:单次分享最大可取(保存)次数上限(0=不限制;expire_style=count 且 expire_value 超上限时 403「限制次数最多为 N 次」) |
expireStyle |
[]string | ["day","hour","minute","forever","count"] |
允许的过期方式白名单(上传时不在白名单 400「过期时间类型错误」) |
存储策略(需求 ④⑩)
| 键 | 类型/边界 | 默认 | 说明 |
|---|---|---|---|
uploadSize |
int64,1024~10GiB | 10485760(10MB) | 单文件大小上限(字节),参考实现语义;max_file_size=0 时作为生效上限 |
max_file_size |
int64,0~10GiB | 0 | 26.9 新增:存储策略-单文件上限(字节),0=回落 uploadSize;超出 403(文案 humanSize 自适应 B/KB/MB/GB)。26.9:管理界面以「MB/GB」下拉单位编辑(≥1 GiB 自动显示 GB),提交时前端换算为字节 |
allowed_file_types |
[]string | ["*"] |
允许类型白名单(扩展名/MIME 通配,* 不限制;非白名单 403「不允许上传该类型文件」) |
storageLimit |
int64,≥0 | 0 | 站点总容量(字节),0=不限制(超限 507) |
openUpload |
int(0/1) | 1 | 游客上传开关(0 时上传接口要求管理员令牌 403) |
enableChunk |
int(0/1) | 0 | 启用分片上传 |
上传频率限制(需求 ④,既有键对齐参考 ip_limit["upload"])
| 键 | 类型/边界 | 默认 | 说明 |
|---|---|---|---|
uploadCount / uploadMinute |
int(1 |
10 / 1 | 窗口内允许上传次数 / 窗口分钟(上传成功才计数,超限 423;管理端修改后运行时同步限流规则,立即生效) |
upload_rate / download_rate |
int64(0~1 GiB/s) | 0 / 0 | 26.9:上下行带宽字节/秒,0=不限速;管理端改后立即生效(每请求动态读 KV)。详见《带宽限速》 |
recycle_enabled |
0/1 | 1 | 26.9:过期分享自动回收开关(定时扫描 + 取件惰性回收) |
recycle_interval |
int64(60~86400 秒) | 1800 | 26.9:回收扫描间隔(秒;管理端以分钟展示) |
retention_days |
int64(0~3650 天) | 0 | 26.9:最长存储时长(天),上传超过该天数的分享自动回收;0=不限制 |
dedup_enabled |
0/1 | 1 | 26.9:SHA512 内容去重,相同文件仅存储一份(多分享引用同一对象,引用计数删除) |
direct_download |
0/1 | 1 | 26.9:对象存储直链下载(S3 引擎 302 到预签名 URL,文件不经过本站带宽) |
direct_link_expire |
int64(60~3600 秒) | 900 | 26.9:直链签名有效期(秒;不超过分享剩余时效) |
hotlink_enabled |
0/1 | 0 | 26.9:下载防盗链(Referer 白名单校验;空 Referer 放行) |
hotlink_whitelist |
string(≤2048) | 空 | 26.9:防盗链白名单,逗号分隔域名,支持 *.example.com 通配;空=仅同源放行 |
errorCount / errorMinute |
int | 10 / 1 | 取件错误(失败计数)+ metadata 每次计数 |
loginCount / loginMinute |
int | 5 / 15 | 登录失败计数 |
安全与会话
| 键 | 默认 | 说明 |
|---|---|---|
admin_token |
空(未初始化) | 管理员密码哈希(sha256$salt$hash);GET 配置时屏蔽为空串 |
jwt_secret |
空 | JWT 签名密钥(初始化/改密时自动生成轮换;不下发;settings.SensitiveKeys 双模式下一致屏蔽) |
adminSessionExpire |
604800(7 天) | 管理员会话秒数(须 1~365 整天) |
存储引擎(26.9 运行时可配 + 热切换)
storage_engine(26.9 新增键):string,local|s3|webdav,默认空=回落启动值 FCB_STORAGE_ENGINE。
运行时切换走 POST /admin/storage/switch(JWT 保护):构建新引擎 → 健康检查通过才生效;
失败返回 503「存储引擎切换失败,已保持原引擎: …」且不改 KV。成功后持久化 storage_engine,重启沿用。
GET /api/v1/config 公开下发 storage_engine 当前名(仅名称,任何引擎参数/凭据不下发)。
引擎参数键(管理端可改;保存后对应引擎实例缓存失效,下次切换/构建生效):
| 键 | 默认 |
|---|---|
file_storage |
local |
storage_path |
空 |
local_storage_path |
空(容器内由 FCB_LOCAL_STORAGE_PATH=/app/data 注入) |
s3_access_key_id / s3_secret_access_key / aws_session_token |
空 |
s3_bucket_name / s3_endpoint_url / s3_hostname |
空 |
s3_region_name |
auto |
s3_signature_version |
s3v4 |
s3_addressing_style |
auto |
s3_proxy |
0 |
webdav_url / webdav_username / webdav_password |
空 |
webdav_root_path |
filebox_storage |
webdav_proxy |
0 |
敏感键
webdav_password/s3_secret_access_key/aws_session_token(26.9 加入settings.SensitiveKeys): 管理端 GET 返回掩码******;PATCH 时空串或******表示不修改。直接写库 settings KV 后重启同样生效。
策略动态生效机制(26.9 需求 ④⑩)
上传页通过 GET /api/v1/config 的 config 字段读取当前策略快照并在范围内渲染选项;
上传链路(/share/file、/chunk/*、/presign/*)每次请求实时读取 settings KV 同一组值校验:
- 管理端改策略(
PATCH /admin/config/update)→ 公开 config 即时反映 → 后续上传立即按新策略执行(含 403/400 拒绝与恢复放行)。 - 生效上限:
max_file_size > 0时为max_file_size,否则回落uploadSize。 - 校验点覆盖:单文件(
/share/file)、分片 init 按分片数上限、分片上传累计、分片 complete 累计、预签名 init 声明大小,五处口径一致(api.UploadPolicy.CheckSize)。
公共配置接口
前端启动时经 GET /api/v1/config 获取站点公开配置(无需认证;26.9 扩展需求 ①②③④⑩):
{
"code": 200, "msg": "ok",
"data": {
"config": {
"name": "文件快传",
"description": "开箱即用的文件快传系统",
"explain": "请勿上传或分享违法内容…",
"logo_url": "",
"favicon_url": "",
"background_url": "",
"footer_text": "自定义页脚内容",
"footer_beian": "京ICP备2024xxxxxx号-1",
"notify_enabled": 1,
"notify_title": "系统通知",
"notify_content": "欢迎使用文件快传…",
"uploadSize": 10485760,
"max_file_size": 10485760,
"maxFileSize": 10485760,
"allowedFileTypes": ["*"],
"expireStyle": ["day", "hour", "minute", "forever", "count"],
"max_save_seconds": 0,
"maxSaveSeconds": 0,
"max_save_count": 0,
"maxSaveCount": 0,
"uploadCount": 10,
"uploadMinute": 1,
"enableChunk": false,
"openUpload": true
},
"meta": {
"version": "26.9",
"features": { "chunkUpload": false, "guestUpload": true }
}
}
}
策略字段 snake_case 与 camelCase 双份下发(前端宽松解析);响应为白名单显式构造, 任何敏感键(
admin_token/jwt_secret)均不会出现。
健康检查
curl -s http://localhost:8466/api/v1/health
{
"code": 200, "msg": "ok",
"data": {
"status": "ok",
"version": "26.9",
"storage": "local",
"time": "2025-06-01T12:00:00+08:00"
}
}