如何使用Spring Data MongoDB通过GridFS ObjectId获取二进制流

ata*_*man 13 mongodb spring-data spring-data-mongodb

我无法弄清楚如何使用spring-data-mongodb从GridFS流式传输二进制文件,以及GridFSTemplate当我已经拥有权限时ObjectId.

GridFSTemplate返回GridFSResource(getResource())或GridFSFile(findX()).

我可以GridFSFile通过ID 获取:

// no way to get the InputStream?
GridFSFile file = gridFsTemplate.findOne(Query.query(Criteria.where("_id").is(id)))
Run Code Online (Sandbox Code Playgroud)

但没有明显的路怎么走一个InputStreamGridFSFile.

只有GridFSResource让我获得corresonding的保持InputStreamInputStreamResource#getInputstream.但获得一个的唯一方法GridFSResource是通过它filename.

// no way to get GridFSResource by ID?
GridFSResource resource = gridFsTemplate.getResource("test.jpeg");
return resource.getInputStream();
Run Code Online (Sandbox Code Playgroud)

不知何故,GridFsTemplateAPI意味着文件名是唯一的 - 它们不是.该GridFsTemplate实现只返回的第一个元素.

现在我正在使用本机MongoDB API,一切都有意义:

GridFS gridFs = new GridFs(mongo);
GridFSDBFile nativeFile = gridFs.find(blobId);
return nativeFile.getInputStream();
Run Code Online (Sandbox Code Playgroud)

看起来我误解了Spring Data Mongo GridFS抽象背后的基本概念.我希望(至少)以下事情之一是可能的/真实的:

  • GridFSResource通过它的ID 得到一个
  • 得到一个GridFSResourceInputStream一个GridFsFile我已经有

我错了,或者这个特定的Spring Data MongoDB API有什么奇怪的东西?

Ste*_*obs 11

我也偶然发现了这一点.我真的很震惊的是,GridFsTemplate的设计是这样的...无论如何,到目前为止,我的丑陋"解决方案":

public GridFsResource download(String fileId) {
    GridFSFile file = gridFsTemplate.findOne(Query.query(Criteria.where("_id").is(fileId)));

    return new GridFsResource(file, getGridFs().openDownloadStream(file.getObjectId()));
}

private GridFSBucket getGridFs() {

    MongoDatabase db = mongoDbFactory.getDb();
    return GridFSBuckets.create(db);
}
Run Code Online (Sandbox Code Playgroud)

注意:你必须注入MongoDbFactory才能工作......


小智 5

这些类型有些混乱:

从Spring GridFsTemplate 来源

public getResource(String location) {

    GridFSFile file = findOne(query(whereFilename().is(location)));
    return file != null ? new GridFsResource(file, getGridFs().openDownloadStream(location)) : null;
}
Run Code Online (Sandbox Code Playgroud)

有一个丑陋的解决方案:

@Autowired
private GridFsTemplate template;

@Autowired
private GridFsOperations operations;

public InputStream loadResource(ObjectId id) throws IOException {
    GridFSFile file = template.findOne(query(where("_id").is(id)));
    GridFsResource resource = template.getResource(file.getFilename());

    GridFSFile file = operations.findOne(query(where("_id").is(id)));
    GridFsResource resource = operations.getResource(file.getFilename());
    return resource.getInputStream();
}
Run Code Online (Sandbox Code Playgroud)