一、问题
原因:默认文件会直接存储到fs桶中,出现找不到文件的情况可能是文件存储到了自定的存储桶中,而GridFsTemplate和GridFSBucket指向的都是默认的存储桶所以查询不到
二、解决方法
首先看源码,创建GridFsTemplate的Bean时有提供构造来选择我们的存储桶
解决:修改自定义存储桶,GridFsTemplate和GridFSBucket都需要重新定义
public GridFsTemplate(MongoDbFactory dbFactory, MongoConverter converter, @Nullable String bucket) {
super(converter);
Assert.notNull(dbFactory, "MongoDbFactory must not be null!");
this.dbFactory = dbFactory;
this.bucket = bucket;
}
点进去查看MongoDbFactory和MongoConverter的源码,可知这两个都是接口,总所周知接口不能实例化,而且这两个参数不能为空,硬要使用可以使用接口的实现类,然后接口实现类不止一个!细看源码,源码注释说的很清楚了,要使用已经给出了的,MongoDbFactory和MongoConverter。首先我们都知道,springboot的ioc依赖注入会把所有的bean类加载到bean容器,那么也就是说,我们可以从bean容器中取出这两个bean
三、实现代码
创建自定义的Bean
@Configuration
public class GridFsConfig {
//获取配置文件中数据库信息
@Value("${spring.data.mongodb.database}")
String db;
@Bean(name = "gridFsMp4Template")
public GridFsTemplate gridFsTestTemplate(MongoDbFactory dbFactory, MongoConverter converter) {
return new GridFsTemplate(dbFactory, converter, "mp4");
}
//GridFSBucket用于打开下载流
@Bean(name="gridMp4BucketTemplate")
public GridFSBucket getGridFSBucket(MongoClient mongoClient){
MongoDatabase mongoDatabase = mongoClient.getDatabase(db);
GridFSBucket bucket = GridFSBuckets.create(mongoDatabase,"mp4");
return bucket;
}
}
使用自定义Bean
@Resource(name = "gridFsMp4Template")
private GridFsTemplate gridFsTestTemplate;
@Resource(name = "gridMp4BucketTemplate")
private GridFSBucket gridFSBucket;
// @Autowired
// private GridFSBucket gridFSBucket;
@Override
public Optional<FileDocument> getFileById(String id) {
FileDocument fileDocument = mongoTemplate.findById(id , FileDocument.class );
if(fileDocument != null){
Query gridQuery = new Query().addCriteria(Criteria.where("_id").is(new ObjectId("62b2b7973830000069004e5e")));
try {
//根据id查询文件
GridFSFile fsFile = gridFsTestTemplate.findOne(gridQuery);
//打开流下载对象
GridFSDownloadStream in = gridFSBucket.openDownloadStream(fsFile.getObjectId());
if(in.getGridFSFile().getLength() > 0){
//获取流对象
GridFsResource resource = new GridFsResource(fsFile, in);
//获取数据
fileDocument.setContent(IoUtil.readBytes(resource.getInputStream()));
return Optional.of(fileDocument);
}else {
fileDocument = null;
return Optional.empty();
}
}catch (IOException ex){
ex.printStackTrace();
}
}
return Optional.empty();
}
我的存储桶文件截图