GridFsTemplate必须显式传入bucket名才能生效,否则默认写入fs桶且无法通过spring.data.mongodb.grid-fs-database等配置切换;真正起作用的是构造时传入的bucket字符串,它决定操作{bucket}.files和{bucket}.chunks集合。

直接用 GridFsTemplate.store() 就能上传,但必须显式传入 bucket 名,否则默认写进 fs 桶,且无法通过配置项切换 —— 这是绝大多数人踩坑的起点。
为什么 spring.data.mongodb.grid-fs-database 配置无效?
这个配置只影响 GridFSBucket 的数据库选择,对 GridFsTemplate 完全无感。真正决定操作哪个集合的是构造时传入的 bucket 字符串:
-
GridFsTemplate底层按{bucket}.files和{bucket}.chunks读写,比如传"tempFs"就操作tempFs.files和tempFs.chunks - 即使你在
application.properties里写了spring.data.mongodb.database=test,又用"tempFs"构造模板,实际操作的仍是test.tempFs.files - 不传 bucket 参数时,
GridFsTemplate固定用fs,哪怕你改了其他配置也无效
如何安全隔离「临时文件」和「正式文件」?
不能靠改配置,必须手动定义多个 @Bean,每个 bean 显式命名并传入不同 bucket 名:
- 用
@Bean(name="gridTempFsTemplate")声明临时桶,构造时传"tempFs" - 用
@Bean(name="gridFormalFsTemplate")声明正式桶,构造时传"formalFs" - 注入时必须用
@Autowired @Qualifier("gridTempFsTemplate"),否则因类型冲突报错 - 不要加
@Primary,会破坏GridFSBucket的自动注入
store() 方法的 contentType 和 metadata 有哪些隐式规则?
GridFsTemplate.store(InputStream, String, String, Document) 第三个参数是 contentType,不是后缀,也不是可选字段:
- 若传
null或空字符串,MongoDB 写入contentType: null,后续用findByContentType()查不到 -
metadata中字段名不能含点(.)或美元符($),否则抛IllegalArgumentException - 推荐统一用
Document.parse("{\"type\":\"image\",\"userId\":\"123\"}")构建metadata,避免BasicDBObject在新版本弃用 - 文件名(第二个参数)存入
filename字段,MongoDB 不校验唯一性,同名文件共存,靠_id区分
真正麻烦的不是上传动作本身,而是 bucket 隔离逻辑没理清就上线 —— 后续查不到、删错桶、跨环境行为不一致,全源于构造时漏传那个字符串参数。


















