SpringData MongoDB GridFsTemplate to save, retrieve, delete binary files (Image, Text files)

MongoDB provides GridFS for storing and retrieving large files with size limit of 16MB. So in the tutorial, JavaSampleApproach will show you how to work with SpringData Mongo GridFsTemplate to save, retrieve, delete binary files (Image, Text files).

Related posts:
Bootstrap Image + MongoDB GridFsTemplate + SpringBoot RestAPI
Spring MongoOperations to access MongoDB
MongoDB – Model One-to-One, One-to-Many Relationships Embedded Documents | SpringBoot

I. Technologies

– Java: 1.8
– Maven: 3.3.9
– Spring Tool Suite: Version 3.8.4.RELEASE
– Spring Boot: 1.5.7.RELEASE
– MongoDB: version v3.4.9

II. SpringData Mongo GridFsTemplate

SpringData MongoDb provides GridFsTemplate class to work with GridFs file, details:


public class GridFsTemplate implements GridFsOperations, ResourcePatternResolver {
...

}

GridFsTemplate implement interface GridFsOperations that is the collection of operations to store and read files from MongoDB GridFS.

For convenient working, SpringBoot provides spring-boot-starter-data-mongodb dependency that is the collection of {mongodb-driver, spring-data-mongodb}.

III. Practice

In the tutorial, we create a SpringBoot project as below:

SpringData Mongo GridFs - project structure

Step to do:
– Create SpringBoot project
– Configure GridFsTemplate
– Implement RestAPIs to work with GridFs files
– Run & check results

1. Create SpringBoot project

Using SpringToolSuite, create a SpringBoot project, then add dependencies:

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>

2. Configure GridFsTemplate

Using AbstractMongoConfiguration to configure GridFsTemplate:


package com.javasampleapproach.gridfstemplate.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.config.AbstractMongoConfiguration;
import org.springframework.data.mongodb.gridfs.GridFsTemplate;

import com.mongodb.Mongo;
import com.mongodb.MongoClient;

@Configuration
public class MongoGridFsTemplate  extends AbstractMongoConfiguration{
	
	@Value("${jsa.mongo.address}")
	private String mongoAddress; 
	
	@Value("${jsa.mongo.database}")
	private String mongoDatabase;
	
	@Bean
	public GridFsTemplate gridFsTemplate() throws Exception {
	    return new GridFsTemplate(mongoDbFactory(), mappingMongoConverter());
	}
	
	@Override
	protected String getDatabaseName() {
		return mongoDatabase;
	}

	@Override
	public Mongo mongo() throws Exception {
		return new MongoClient(mongoAddress);
	}
}

Open application.properties file, add configuration:


jsa.mongo.address=127.0.0.1
jsa.mongo.database=jsa-mongodb

3. Implement RestAPIs to work with GridFs files

Using GridFsOperations to implement 4 RestfulAPIs {/api/save, /api/retrieve/imagefile, /api/retrieve/textfiles, /api/delete/image}:


package com.javasampleapproach.gridfstemplate.controller;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.gridfs.GridFsOperations;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import com.mongodb.gridfs.GridFSDBFile;

@RestController
@RequestMapping("/api")
public class RestControllerAPIs {

	@Autowired
	GridFsOperations gridOperations;
	
	// this variable is used to store ImageId for other actions like: findOne or delete
	private String imageFileId = "";

	@GetMapping("/save")
	public String saveFiles() throws FileNotFoundException {
		// Define metaData
		DBObject metaData = new BasicDBObject();
		metaData.put("organization", "JavaSampleApproach");
		
		/**
		 * 1. save an image file to MongoDB
		 */
		
		// Get input file
		InputStream iamgeStream = new FileInputStream("D:\\JSA\\jsa-logo.png");
		
		metaData.put("type", "image");
		
		// Store file to MongoDB
		imageFileId = gridOperations.store(iamgeStream, "jsa-logo.png", "image/png", metaData).getId().toString();
		System.out.println("ImageFileId = " + imageFileId);

		/**
		 * 2. save text files to MongoDB
		 */
		
		// change metaData
		metaData.put("type", "data");

		// Store files to MongoDb
		gridOperations.store(new FileInputStream("D:\\JSA\\text-1.txt"), "text-1.txt", "text/plain", metaData);
		gridOperations.store(new FileInputStream("D:\\JSA\\text-2.txt"), "text-2.txt", "text/plain", metaData);

		return "Done";
	}
	
	@GetMapping("/retrieve/imagefile")
	public String retrieveImageFile() throws IOException{
		// read file from MongoDB
		GridFSDBFile imageFile = gridOperations.findOne(new Query(Criteria.where("_id").is(imageFileId)));
		
		// Save file back to local disk
		imageFile.writeTo("D:\\JSA\\retrieve\\jsa-logo.png");
		
		System.out.println("Image File Name:" + imageFile.getFilename());
		
		return "Done";
	}
	
	@GetMapping("/retrieve/textfiles")
	public String retrieveTextFiles(){
		/**
		 * get all data files then save to local disk
		 */
		
		// Retrieve all data files
		List textFiles = gridOperations.find(new Query(Criteria.where("metadata.type").is("data")));
		
		// Save all back to local disk
		textFiles.forEach(file->{
			
			try {
				String fileName = file.getFilename();
				
				file.writeTo("D:\\JSA\\retrieve\\"+ fileName);
				
				System.out.println("Text File Name: " + fileName);
				
			} catch (IOException e) {
				e.printStackTrace();
			}
		});
		
		return "Done";
	}
	
	@GetMapping("/delete/image")
	public String deleteFile(){
		// delete image via id
		gridOperations.delete(new Query(Criteria.where("_id").is(imageFileId)));
		
		return "Done";
	}
}

4. Run & check results

Build and Run the SpringBoot project with commandlines: {mvn clean install, mvn spring-boot:run}.

– Make a saving request: http://localhost:8080/api/save

SpringData Mongo GridFs - save results

– Make a retrieving image request: http://localhost:8080/api/retrieve/imagefile

SpringData Mongo GridFs - retrieve image file

– Make a retrieving textfiles request: http://localhost:8080/api/retrieve/textfiles

SpringData Mongo GridFs - retrieve text files

– Make a delete request: http://localhost:8080/api/delete/image

SpringData Mongo GridFs - after delete

IV. Sourcecode

SpringDataGridFsTemplate



By grokonez | September 18, 2017.

Last updated on April 10, 2021.



Related Posts


4 thoughts on “SpringData MongoDB GridFsTemplate to save, retrieve, delete binary files (Image, Text files)”

  1. Hi.
    I’m trying to use your code.

    saveFiles works ok and create documents in mongo, but retrieveImageFile give me an error in the next line:

    GridFSDBFile imageFile = gridOperations.findOne(new Query(Criteria.where(“_id”).is(imageFileId)));

    Type mismatch: cannot convert from GridFSFile to GridFSDBFile

    Tried to change GridFSDBFile to GridFSFile but then imageFile.writeTo doesn’t work.

    Any idea?
    Thanks

    1. May be you are working with Spring Boot 2.0.x that GridFS operations are mowing towards Resource.
      You can try with a solution below:

      gridFsTemplate.getResource("your-file-name.txt")

      Regards,
      JSA

  2. When i try to do read or write i am getting com.mongodb.MongoQueryException: Query failed with error code 13 and error message ‘there are no users authenticated’ on server

Got Something To Say:

Your email address will not be published. Required fields are marked *

*