GridFS Support

MongoDB supports storing binary files inside its filesystem, GridFS. Spring Data MongoDB provides a GridFsOperations and ReactiveGridFsOperations interface as well as the corresponding implementation, GridFsTemplate and ReactiveGridFsTemplate, to let you interact with the filesystem. You can set up a template instance by handing it a MongoDatabaseFactory/ReactiveMongoDatabaseFactory as well as a MongoConverter, as the following example shows:

  • Imperative

  • Reactive

  • XML

class GridFsConfiguration extends AbstractMongoClientConfiguration {

  // … further configuration omitted

  @Bean
  public GridFsTemplate gridFsTemplate() {
    return new GridFsTemplate(mongoDbFactory(), mappingMongoConverter());
  }
}
class ReactiveGridFsConfiguration extends AbstractReactiveMongoConfiguration {

  // … further configuration omitted

  @Bean
  public ReactiveGridFsTemplate reactiveGridFsTemplate() {
    return new ReactiveGridFsTemplate(reactiveMongoDbFactory(), mappingMongoConverter());
  }
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:mongo="http://www.springframework.org/schema/data/mongo"
xsi:schemaLocation="http://www.springframework.org/schema/data/mongo
https://www.springframework.org/schema/data/mongo/spring-mongo.xsd
http://www.springframework.org/schema/beans
https://www.springframework.org/schema/beans/spring-beans.xsd">

  <mongo:db-factory id="mongoDbFactory" dbname="database" />
  <mongo:mapping-converter id="converter" />

  <bean class="org.springframework.data.mongodb.gridfs.GridFsTemplate">
    <constructor-arg ref="mongoDbFactory" />
    <constructor-arg ref="converter" />
  </bean>

</beans>

The template can now be injected and used to perform storage and retrieval operations, as the following example shows:

Using GridFS to store files
  • Imperative

  • Reactive

class GridFsClient {

  @Autowired
  GridFsOperations operations;

  @Test
  public void storeFileToGridFs() {

    FileMetadata metadata = new FileMetadata();
    // populate metadata
    Resource file = … // lookup File or Resource

    operations.store(file.getInputStream(), "filename.txt", metadata);
  }
}

The store(…) operations take an InputStream, a filename, and (optionally) metadata information about the file to store. The metadata can be an arbitrary object, which will be marshaled by the MongoConverter configured with the GridFsTemplate. Alternatively, you can also provide a Document.

class ReactiveGridFsClient {

  @Autowired
  ReactiveGridFsTemplate operations;

  @Test
  public Mono<ObjectId> storeFileToGridFs() {

    FileMetadata metadata = new FileMetadata();
    // populate metadata
    Publisher<DataBuffer> file = … // lookup File or Resource

    return operations.store(file, "filename.txt", metadata);
  }
}

The store(…) operations take an Publisher<DataBuffer>, a filename, and (optionally) metadata information about the file to store. The metadata can be an arbitrary object, which will be marshaled by the MongoConverter configured with the ReactiveGridFsTemplate. Alternatively, you can also provide a Document.

The MongoDB’s driver uses AsyncInputStream and AsyncOutputStream interfaces to exchange binary streams. Spring Data MongoDB adapts these interfaces to Publisher<DataBuffer>. Read more about DataBuffer in Spring’s reference documentation.

You can read files from the filesystem through either the find(…) or the getResources(…) methods. Let’s have a look at the find(…) methods first. You can either find a single file or multiple files that match a Query. You can use the GridFsCriteria helper class to define queries. It provides static factory methods to encapsulate default metadata fields (such as whereFilename() and whereContentType()) or a custom one through whereMetaData(). The following example shows how to use the template to query for files:

Using GridFsTemplate to query for files
  • Imperative

  • Reactive

class GridFsClient {

  @Autowired
  GridFsOperations operations;

  @Test
  public void findFilesInGridFs() {
    GridFSFindIterable result = operations.find(query(whereFilename().is("filename.txt")));
  }
}
class ReactiveGridFsClient {

  @Autowired
  ReactiveGridFsTemplate operations;

  @Test
  public Flux<GridFSFile> findFilesInGridFs() {
    return operations.find(query(whereFilename().is("filename.txt")))
  }
}
Currently, MongoDB does not support defining sort criteria when retrieving files from GridFS. For this reason, any sort criteria defined on the Query instance handed into the find(…) method are disregarded.

The other option to read files from the GridFs is to use the methods introduced by the ResourcePatternResolver interface. They allow handing an Ant path into the method and can thus retrieve files matching the given pattern. The following example shows how to use GridFsTemplate to read files:

Using GridFsTemplate to read files
  • Imperative

  • Reactive

class GridFsClient {

  @Autowired
  GridFsOperations operations;

  public GridFsResources[] readFilesFromGridFs() {
     return operations.getResources("*.txt");
  }
}
class ReactiveGridFsClient {

  @Autowired
  ReactiveGridFsOperations operations;

  public Flux<ReactiveGridFsResource> readFilesFromGridFs() {
     return operations.getResources("*.txt");
  }
}

GridFsOperations extends ResourcePatternResolver and lets the GridFsTemplate (for example) to be plugged into an ApplicationContext to read Spring Config files from MongoDB database.

By default, GridFsTemplate obtains GridFSBucket once upon the first GridFS interaction. After that, the template instance reuses the cached bucket. To use different buckets, from the same Template instance use the constructor accepting Supplier<GridFSBucket>.