使用GridFsTemplate在mongodb中存取文件 spring-data-mongodb之gridfs Store Retrive and Query Image File Using Mongodb GridFs And Spring Data

 

mongodb除了能够存储大量的数据外,还内置了一个非常好用的文件系统。
基于mongodb集群的优势,GridFS当然也是分布式的,而且备份也方便。
当用户把文件上传到GridFS后,文件会被分割成大小为256KB的块,并单独存放起来。

好处如下:

  1. 可以有Replication;
  2. 可以利用MongoDB的权限访问控制;
  3. 可以利用现成的MongoDB备份方式;

今天主要是学习如何使用data这个框架来操作GridFS

首先配置gridFs的模板类

<!-- Mongodb gridFs的模板 -->
 <bean id="gridFsTemplate" class="org.springframework.data.mongodb.gridfs.GridFsTemplate">
     <constructor-arg ref="mongoDbFactory" />
     <constructor-arg ref="mappingConverter" />
 </bean>
/**
  * 上传文件
  * @author yinjihuan
  * @throws Exception
  */
 public static void uploadFile() throws Exception {
     File file = new File("/Users/yinjihuan/Downlaods/logo.png");
     InputStream content = new FileInputStream(file);
     //存储文件的额外信息,比如用户ID,后面要查询某个用户的所有文件时就可以直接查询
     DBObject metadata = new BasicDBObject("userId", "1001");
     GridFSFile gridFSFile = gridFsTemplate.store(content, file.getName(), "image/png", metadata);
     String fileId = gridFSFile.getId().toString();
     System.out.println(fileId);
 }

文件默认是上传到数据中的fs.files和fs.chunks中
files是用来存储文件的信息,文件名,md5,文件大小,还有刚刚的metadata,上传时间等等数据,数据格式如下:

{
    "_id": ObjectId("57c17bb0d4c666b6e53ba795"),
    "metadata": {
        "user_id": 1001
    },
    "filename": "file",
    "aliases": null,
    "chunkSize": NumberLong(261120),
    "uploadDate": ISODate("2016-09-08T11:38:24.999Z"),
    "length": NumberLong(165253),
    "contentType": "image/png",
    "md5": "668727a643ddd6df2e98f164d9fc90fd"
}

chunks则是用来存储文件内容的
1.files_id就是文件的ID,也就是files集合中的_id
2.n是文件块的索引,通常文件会被分割成256KB的块大小存储
3.data就是文件的数据了

当需要访问文件的时候通过文件ID可以找到文件被分成了多少块,然后从第一块按顺序开始读取,返回给用户。

{
    "_id": ObjectId("57c18993d4c6355ffeb6f8ae"),
    "files_id": ObjectId("57c17bb0d4c666b6e53ba795"),
    "n": 0,
    "data": BinData(0,
    "iVBORw0KGgDSDDSDDSD5xNvmxT5/sHLl5oDl/Y/NtznsPTPllg9+Gqie+Yj5xNvmxT5/sHLl5oDl/Y/NtznsPTPllg9+Gqie+YjoA")
}
{
    "_id": ObjectId("57c18993d4c6355ffeb6f8ae"),
    "files_id": ObjectId("57c17bb0d4c666b6e53ba795"),
    "n": 1,
    "data": BinData(1,
    "iVBORw0KGgDSDDSDDSD5xNvmxT5/sHLl5oDl/Y/NtznsPTPllg9+Gqie+Yj5xNvmxT5/sHLl5oDl/Y/NtznsPTPllg9+Gqie+YjoA")
}
/**
  * 根据文件ID查询文件
  * @author yinjihuan
  * @param fileId
  * @return
  * @throws Exception
  */
 public static GridFSDBFile getFile(String fileId) throws Exception {
     return gridFsTemplate.findOne(Query.query(Criteria.where("_id").is(fileId)));
 }
/**
  * 根据文件ID删除文件
  * @author yinjihuan
  * @param fileId
  * @throws Exception
  */
 public static void removeFile(String fileId) throws Exception {
     gridFsTemplate.delete(Query.query(Criteria.where("_id").is(fileId)));
 }

如果在Spring mvc中想直接访问存储的文件也很简单,直接通过文件ID查询该文件,然后直接输出到response就是了,记得要设置ContentType,这时就明白为什么存储的时候要把ContentType存起来了。

/**
  * 访问图片
  * @author yinjihuan
  * @param fileId
  * @param request
  * @param response
  */
 @RequestMapping(value = "/image/{fileId}")
 @ResponseBody
 public void getImage(@PathVariable String fileId, HttpServletResponse response) {
     try {
         GridFSDBFile gridfs = filesService.getFile(fileId);
         response.setContentType(gridfs.getContentType());
         OutputStream out = response.getOutputStream();
         gridfs.writeTo(out);
         out.flush();
         out.close();
     } catch (Exception e) {
          e.printStackTrace();
     }
 }

源码下载:https://github.com/yinjihuan/cxytiandi

Store Retrive and Query Image File Using Mongodb GridFs And Spring Data

  

In previous tutorials, we learned about How to Install Mongodb On Windows platform and Implement CRUD Operations Using MongoDB And Spring Data. This tutorial will help to store,retrieve image file using Mongodb GridFs specification.

 

Tools and Technologies

Basically we are using below maven dependencies

  1. Maven 3.0.4
  2. JDK 1.6
  3. Spring Core 4.0.3.RELEASE
  4. Spring Data Mongodb 1.5.2.RELEASE

Maven Dependencies

We need to define required dependencies and their versions in pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <modelVersion>4.0.0</modelVersion>
 <groupId>org.springframework.data.examples</groupId>
 <artifactId>spring-data-examples</artifactId>
 <version>0.0.1-SNAPSHOT</version>
 <name>SpringMongoExamples</name>
 <dependencies>
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-core</artifactId>
   <version>4.0.3.RELEASE</version>
  </dependency>
  <dependency>
   <groupId>org.springframework.data</groupId>
   <artifactId>spring-data-mongodb</artifactId>
   <version>1.5.2.RELEASE</version>
  </dependency>

 </dependencies>
 <build>
  <finalName>SpringMongoExamples</finalName>
  <plugins>
   <plugin>
    <artifactId>maven-compiler-plugin</artifactId>
    <configuration>
     <source>1.6</source>
     <target>1.6</target>
    </configuration>
   </plugin>
  </plugins>
 </build>
</project>

org.springframework I am using spring 4.0.3.RELEASE version. we required only spring-core artifact of Spring Framework because this is stand-alone java application

org.springframework.data Spring Data for MongoDB is part of the parent Spring Data project. You can define the respected dependency in pom.xml

Once you define your maven dependencies in pom.xml, please execute the maven command mvn clean install -e so that it will start downloading the respected jars files

使用GridFsTemplate在mongodb中存取文件
spring-data-mongodb之gridfs
Store Retrive and Query Image File Using Mongodb GridFs And Spring Data

FileStorageDao Interface

Here we are going to use DAO pattern to perform Db operation with MongoDb, Which store and retrive the image File. So lets define below methods in FileStorageDao interface.

package com.technicalkeeda.dao;

import java.io.InputStream;
import java.util.List;

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

public interface FileStorageDao {

 public String store(InputStream inputStream, String fileName,
   String contentType, DBObject metaData);
 
 public GridFSDBFile retrive(String fileName);

 public GridFSDBFile getById(String id);

 public GridFSDBFile getByFilename(String filename);

 public List findAll();

}

FileStorageDao Implementation

This is MongoDB specific implementation to perform different Image operations using GridFsTemplate similar to MongoTemplate. Its not specific to Image file you can store or save any type of files like .doc, .xls and.pdf etc.

The template can now be injected and used to perform storage and retrieval operations.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 marshalled by the MongoConverter configured with the GridFsTemplate

package com.technicalkeeda.dao;

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.GridFsTemplate;

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

public class FileStorageDaoImpl implements FileStorageDao {

 @Autowired
 GridFsTemplate gridFsTemplate;

 public String store(InputStream inputStream, String fileName,
   String contentType, DBObject metaData) {
  return this.gridFsTemplate
    .store(inputStream, fileName, contentType, metaData).getId()
    .toString();
 }

 public GridFSDBFile getById(String id) {
  return this.gridFsTemplate.findOne(new Query(Criteria.where("_id").is(
    id)));
 }

 public GridFSDBFile getByFilename(String fileName) {
  return gridFsTemplate.findOne(new Query(Criteria.where("filename").is(
    fileName)));
 }

 public GridFSDBFile retrive(String fileName)