GridFS在Spring Boot中需手动配置,因spring-boot-starter-data-mongodb不自动装配GridFsTemplate或GridFSBucket;推荐使用GridFSBucket(需显式@Bean注册),依赖MongoDatabase而非MongoTemplate,上传时将关键字段存入metadata并手动建索引,下载须流式处理防OOM。

GridFS 在 Spring Boot 里没有开箱即用的自动配置
Spring Boot 的 spring-boot-starter-data-mongodb 只支持普通文档操作,GridFS 不在默认装配范围内。你得手动注册 GridFsTemplate 或直接用 MongoClient 拿 GridFSBucket —— 否则一调 gridFsTemplate.store(...) 就报 NoSuchBeanDefinitionException。
常见错误现象:Field gridFsTemplate required a bean of type 'org.springframework.data.mongodb.gridfs.GridFsTemplate' that could not be found
- 必须显式声明
@Bean,不能只靠 starter 自动扫 - 推荐用
GridFSBucket(原生驱动 API),比老版GridFsTemplate更轻、更可控,且 Spring Data MongoDB 3.0+ 已标记后者为 deprecated - 注意
GridFSBucket依赖MongoDatabase,不是MongoTemplate;别错传了 bean
怎么正确创建 GridFSBucket 实例
核心是拿到 MongoDatabase,再用 GridFSBuckets.create(...) 构造。别手写 new —— 它没公开构造函数。
使用场景:上传文件、按 ID 查询、流式下载、删除旧版本文件
- 从
MongoClient获取MongoDatabase,数据库名建议和业务库一致(如"myapp"),避免跨库权限问题 - 可指定 bucket 名(如
"files"),不指定则用默认"fs";多个 bucket 要确保名字不冲突,否则读写会串 - 如果用了分片集群,
GridFS的chunks和files集合默认不自动分片,大文件吞吐可能成瓶颈
@Bean
public GridFSBucket gridFSBucket(MongoClient mongoClient) {
MongoDatabase database = mongoClient.getDatabase("myapp");
return GridFSBuckets.create(database, "files");
}
上传文件时 metadata 怎么存才方便查
GridFSBucket.uploadFromStream() 接收一个 Document 作为元数据,这是唯一能附带结构化信息的地方。别指望靠 filename 字段模糊查 —— 它不建索引,默认查起来慢。
性能影响:不加索引的 metadata 字段查询会触发 collection scan
- 把关键检索字段放进 metadata,比如
"userId"、"type"、"version" - 手动在
files集合上建索引:db.fs.files.createIndex({"metadata.userId": 1, "metadata.type": 1}) - filename 只建议存原始名称(含扩展名),不要拼路径或加哈希前缀 —— GridFS 本身不解析路径语义
- 避免在 metadata 存大文本或嵌套过深,MongoDB 单文档上限 16MB,而
files文档本身也计入
下载文件流为什么容易 OOM 或阻塞
直接调 gridFSBucket.openDownloadStream() 返回的是 GridFSFindIterable,但真正触发读取是在你调 .read() 或转 InputStream 时。如果没设超时、没关流、没限速,小文件没问题,大文件(>100MB)极易拖垮服务。
容易踩的坑:GridFSDownloadStream 是一次性流,不可 reset,也不支持 range 请求(除非自己封装 HTTP Range 处理)
- 务必用 try-with-resources 包裹
GridFSDownloadStream,它实现了AutoCloseable - 对外提供下载接口时,别直接返回整个 byte[],用
ResponseEntity<streamingresponsebody></streamingresponsebody>流式写回 - 设置读超时:
gridFSBucket.find(...).first().get().getLength()先查大小,超阈值就拒掉 - 别在 WebFlux 场景混用阻塞式
GridFSDownloadStream,要用ReactiveGridFsTemplate(需spring-boot-starter-data-mongodb-reactive)

















