[[gridfs]]
= GridFS Support

MongoDB supports storing binary files inside its filesystem, GridFS.
Spring Data MongoDB provides a javadoc:org.springframework.data.mongodb.gridfs.GridFsOperations[] and javadoc:org.springframework.data.mongodb.gridfs.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:

[tabs]
======
Imperative::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
class GridFsConfiguration extends AbstractMongoClientConfiguration {

  // … further configuration omitted

  @Bean
  public GridFsTemplate gridFsTemplate() {
    return new GridFsTemplate(mongoDbFactory(), mappingMongoConverter());
  }
}
----

Reactive::
+
[source,java,indent=0,subs="verbatim,quotes",role="secondary"]
----
class ReactiveGridFsConfiguration extends AbstractReactiveMongoConfiguration {

  // … further configuration omitted

  @Bean
  public ReactiveGridFsTemplate reactiveGridFsTemplate() {
    return new ReactiveGridFsTemplate(reactiveMongoDbFactory(), mappingMongoConverter());
  }
}
----

XML::
+
[source,xml,indent=0,subs="verbatim,quotes",role="secondary"]
----
<?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
[tabs]
======
Imperative::
+
====
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
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`.
====

Reactive::
+
====
[source,java,indent=0,subs="verbatim,quotes",role="secondary"]
----
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-framework-docs}/core/databuffer-codec.html[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
[tabs]
======
Imperative::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
class GridFsClient {

  @Autowired
  GridFsOperations operations;

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

Reactive::
+
[source,java,indent=0,subs="verbatim,quotes",role="secondary"]
----
class ReactiveGridFsClient {

  @Autowired
  ReactiveGridFsTemplate operations;

  @Test
  public Flux<GridFSFile> findFilesInGridFs() {
    return operations.find(query(whereFilename().is("filename.txt")))
  }
}
----
======

NOTE: 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
[tabs]
======
Imperative::
+
[source,java,indent=0,subs="verbatim,quotes",role="primary"]
----
class GridFsClient {

  @Autowired
  GridFsOperations operations;

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

Reactive::
+
[source,java,indent=0,subs="verbatim,quotes",role="secondary"]
----
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.

NOTE: 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>`.
