spring boot 默认只配一个绑定 fs 桶的 gridfstemplate,且不响应 spring.data.mongodb.grid-fs-database;多桶、换库、隔离文件类型必须手动声明 bean 并显式传入 bucket 名。

Spring Boot 默认只配一个 GridFsTemplate,绑定到 fs 桶,且不响应 spring.data.mongodb.grid-fs-database 配置项;想用多桶、换库、隔离文件类型,必须手动声明 bean 并显式传入 bucket 名。
为什么 new GridFsTemplate() 必须传 bucket 名
Spring Boot 自动配置的 GridFsTemplate 底层固定使用 "fs" 作为 bucket,哪怕你改了数据库名或加了其他配置,它操作的仍是 db.fs.files 和 db.fs.chunks。要写进 tempFs 或 backup,就得自己 new 实例,并把 bucket 名作为第三个参数传进去:
-
new GridFsTemplate(mongoDbFactory, converter, "tempFs")→ 操作db.tempFs.files - 不传第三个参数,等价于
new GridFsTemplate(..., "fs"),无法覆盖 - 每个自定义 bean 必须用
@Bean(name = "tempGridFsTemplate")显式命名,否则@Autowired会因类型冲突失败
application.properties 的配置对 GridFsTemplate 无效
很多人误以为加这行就能切 bucket:
spring.data.mongodb.grid-fs-database=custom_db
其实它只影响 GridFSBucket 的数据库选择,对 GridFsTemplate 完全无感。真正起作用的是构造时传的 bucket 字符串——它决定操作哪一组集合(如 custom_db.tempFs.files),而不是配置项。
-
spring.data.mongodb.database=test+"tempFs"构造 → 实际操作test.tempFs.files -
spring.data.mongodb.grid-fs-database只在用GridFSBucket.builder().build()时才生效 - 不要用
@Primary替换默认 bean,会导致GridFSBucket注入失败
metadata 中的时间、枚举等字段必须手动序列化
GridFsTemplate.store() 传入的 Document 会被原样写入 .files 集合的 metadata 字段,不走 Spring Data 的 @WritingConverter 链路。BSON 编码器不认识 LocalDateTime 或自定义枚举,直接塞进去会报错或存空。
-
LocalDateTime→ 推荐转成String:DateTimeFormatter.ISO_LOCAL_DATE_TIME.format(time) - 或转成毫秒值:
time.atZone(ZoneOffset.UTC).toInstant().toEpochMilli() - 枚举统一用
myEnum.name(),别用ordinal() - metadata 键名不能含
.或$,否则抛IllegalArgumentException
contentType 参数不是可选字段,也不能传后缀
GridFsTemplate.store(InputStream, String, String, Document) 的第三个参数是 contentType,不是文件扩展名,也不接受 null 或空字符串:
- 传
null或""→ MongoDB 存contentType: null→ 后续findByContentType()查不到 - 应传标准 MIME 类型,如
"image/png"、"application/pdf" - 文件名(第二个参数)仅存入
filename字段,MongoDB 不校验唯一性,同名文件会共存
bucket 名就是集合前缀,它决定了物理存储位置;metadata 序列化和 contentType 是运行时最容易崩的两个点,不提前处理,上线后查不到文件、删不掉临时文件都是常态。











