65ebf8de90
文件以前直接写本地磁盘:两个实例各存各的,学生这次传到 A、下次请求落到 B,
文件就"不见了"。这不是性能问题,是正确性问题 —— 它一直卡着不上多副本。
新增:
· module/file/storage/{StorageService,LocalStorageService,QiniuStorageService}
· config/StorageConfig(装配 + 可选启动自检)
· FillProperties 新增 fill.storage
· MaterialFileController 新增 GET /{id}/url(签名链接)与 GET /{id}/content
· scripts/e2e-m1-storage.py(存储自检,没配七牛时跳过而非失败)
关键设计:
① 业务只认 path(std/1/17/张同学-…-身份证.jpg),各实现自己映射成真实位置:
本地 ./data/uploads/std/...、七牛 xiaotutongxue/std/...
**换存储不用改数据库、不用改业务代码**
② 空间私有 → 下载必须签名。GET /{id}/url 每次现签(默认 30 分钟),
所以这个 URL 绝不能长期保存:写进库、塞进导出的 Excel、发给学生明天再打开,都是 403
③ 对象键里有中文,拼 URL **必须逐段编码** —— 整串 encode 会把 / 编成 %2F,
那在七牛那边是另一个键,表现是"传上去了却打不开",且报错什么都没有
④ 区域默认 auto:华东-浙江在新旧控制台对应 z0 与 cn-east-2,
写错了的症状是**上传超时**——一个从报错完全看不出原因的失败
⑤ AK/SK 不进仓库也不进 jar:dev.yml 只放占位符;
真密钥在 backend/application-local.yml(已 gitignore),
用 spring.config.import: optional:**file**:./application-local.yml
—— 刻意用 file: 而不是 classpath:,后者会被打进 jar,密钥就跟着构建产物走了
⑥ 配了 qiniu 却没密钥 → 启动就炸(fail-fast):起得来的话第一个受害的是
正在填材料的学生,而排查要从"文件保存失败"一路追到环境变量
已验证:存储抽象改造没破坏任何现有链路 —— 本地磁盘路径下
e2e-m3-file 29/29、m3-submit 31/31、m1-materials 68/68、m3-draft 27/27 全绿;
启动日志打出「本地磁盘(多副本部署下会丢文件)」;git check-ignore 确认
application-local.yml 被忽略而 .example 不被忽略。
⏳ 未验证:**七牛的真实链路没跑过** —— 用户给了域名/空间/区域/私有/目录前缀,
但没给 AccessKey/SecretKey,没有它生成不了上传凭证。
补上后跑 python scripts/e2e-m1-storage.py 即可(它会验:配置齐全 →
上传处理落进七牛 → 取签名链接 → 真的下载回来比字节 → 不带签名被拒
→ 对象键带前缀 → 原始件一字不差)。没配时脚本跳过并 exit 0,不误报失败。
64 lines
1.5 KiB
Plaintext
64 lines
1.5 KiB
Plaintext
# ── IDE ──────────────────────────────
|
||
.idea/
|
||
*.iml
|
||
.vscode/
|
||
*.swp
|
||
|
||
# ── Java / Maven ─────────────────────
|
||
target/
|
||
*.class
|
||
*.jar
|
||
!**/gradle/wrapper/*.jar
|
||
.mvn/wrapper/maven-wrapper.jar
|
||
|
||
# ── Node / 前端 ───────────────────────
|
||
node_modules/
|
||
dist/
|
||
dist-ssr/
|
||
unpackage/
|
||
.pnpm-store/
|
||
*.tsbuildinfo
|
||
|
||
# ── 环境与密钥(禁止入库)────────────
|
||
.env
|
||
.env.local
|
||
.env.*.local
|
||
*.pem
|
||
*.key
|
||
*.p12
|
||
keystore/
|
||
|
||
# ── 日志与运行时 ──────────────────────
|
||
logs/
|
||
*.log
|
||
npm-debug.log*
|
||
yarn-error.log*
|
||
|
||
# ── 构建产物 ──────────────────────────
|
||
build/
|
||
out/
|
||
*.tmp
|
||
*.bak
|
||
|
||
# ── Python(scripts/ 下的验收与工具脚本)──
|
||
# 跑 python -m py_compile 或导入脚本时会生成字节码,不该入库
|
||
__pycache__/
|
||
*.py[cod]
|
||
|
||
# ── 上传/导出的本地测试数据 ───────────
|
||
/data/
|
||
/upload/
|
||
/export/
|
||
*.zip
|
||
|
||
# ── OS ───────────────────────────────
|
||
.DS_Store
|
||
Thumbs.db
|
||
desktop.ini
|
||
|
||
# 运行时上传的文件(材料原图/规范件)—— 是数据不是代码,绝不入库
|
||
backend/data/
|
||
|
||
# 本地私有配置(云存储密钥等)—— 只提交 .example 模板
|
||
application-local.yml
|