Spring项目使用Mongodb中GridFS实现文件上传下载查找(附效果图)

1.前言

     最近公司实习,需要使用Mongodb实现文件上传下载功能。我之前也没接触过相应的项目,只好从Mongodb概念开始看...看了好多文章感觉都不是我想要的功能代码。我的需求是能从浏览器中选择文件上传,或者输入文件ID号就能下载。以下的两篇文章是我找到比较好的(也就是Ctrl+V就能运行的代码QAQ)。第一篇是官方文档讲得比较好,第二篇是github一个项目。结合这两篇文章我写了该需求的代码。先看效果:

2.文件上传

2.1网页前端选择

Spring项目使用Mongodb中GridFS实现文件上传下载查找(附效果图)_第1张图片

 2.2控制台输出:

2.3Mongodb数据库:这里用的可视化工具Robo 3T

fs.files

Spring项目使用Mongodb中GridFS实现文件上传下载查找(附效果图)_第2张图片

fs.chunks

3.文件下载

请求传入刚才的文件Id就能下载

Spring项目使用Mongodb中GridFS实现文件上传下载查找(附效果图)_第3张图片

 

这样一个使用Mongodb文件上传下载流程就基本实现了TAT。如果有相同的需求就接着看吧。

4.实现代码

4.1maven配置:

        
		    org.springframework.boot
		    spring-boot-starter-data-mongodb
		

4.2spring配置:

spring:
     data:
        mongodb:
          #host: 127.0.0.1
          #port: 27017
          #database: admin
          uri: mongodb://localhost:27017/db

4.3controller代码


import com.mongodb.Block;
import com.mongodb.MongoClient;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.gridfs.GridFSBucket;
import com.mongodb.client.gridfs.GridFSBuckets;
import com.mongodb.client.gridfs.model.GridFSFile;
import com.mongodb.client.gridfs.model.GridFSUploadOptions;
import com.mongodb.gridfs.GridFS;
import com.mongodb.gridfs.GridFSDBFile;
import org.bson.BsonValue;
import org.bson.Document;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.*;



@Controller
@RequestMapping("/files")
public class FileController {


    @Autowired
    private GridFS gridFS;

    private MongoClient mongoClient = new MongoClient("localhost", 27017);

    private MongoDatabase myDatabase = mongoClient.getDatabase("db");

    private GridFSBucket gridFSBucket = GridFSBuckets.create(myDatabase);

    /**
     * 上传文件
     *
     * @param file 文件
     * @return 文件名和文件存储的fileId键值对的Map
     */
    @RequestMapping(value = "/upload", method = RequestMethod.POST)
    public Map upload(@RequestParam(value = "file") MultipartFile file) {

        Map map = new HashMap<>();
        try {
            InputStream streamToUploadFrom = file.getInputStream();

            Document document = new Document();
            //自定义数据,放入文件真正名和文件类型
            document.append("fileTrueName", file.getOriginalFilename());
            document.append("contentType", file.getContentType());
            //设置chunks长度为358400字节,如果文件过大则创建新的分块
            // 自定义的数据放在metadata里
            GridFSUploadOptions options = new GridFSUploadOptions()
                    .chunkSizeBytes(358400)
                    .metadata(document);

            ObjectId fileId = gridFSBucket.uploadFromStream(UUID.randomUUID().toString(), streamToUploadFrom, options);
            System.out.println("上传成功," + "文件名:" + file.getOriginalFilename() + "文件ID:" + fileId);
            map.put(file.getOriginalFilename(), fileId);

        } catch (Exception e) {
            e.printStackTrace();
        }
        return map;
    }

    /**
     * 通过文件fileId下载文件
     *
     * @param fileId 文件fileId
     * @param response 文件输出流
     */
    @RequestMapping(value = "/downLoadByFileId")
    public void downLoadByFileId(@RequestParam(value = "fileId") ObjectId fileId, HttpServletResponse response) {

        GridFSDBFile gridFSDBFile = gridFS.findOne(fileId);

        try {
            //获取回复的输出流
            OutputStream sos = response.getOutputStream();
            //设置编码格式
            response.setCharacterEncoding("UTF-8");
            response.setHeader("Access-Control-Allow-Origin", "*");
            //设置文件返回类型,为上传文件时获取的文件类型
            response.setContentType(gridFSDBFile.getMetaData().get("contentType").toString());
            response.addHeader("Content-Disposition", "attachment; filename=\"" + gridFSDBFile.getMetaData().get("fileTrueName") + "\"");
            //将查询到的数据放入到输出流sos中
            gridFSDBFile.writeTo(sos);
            sos.flush();
            sos.close();

        } catch (Exception e) {
            e.printStackTrace();
        }


    }

    /**
     * 获取所有文件fileId
     */
    @ResponseBody
    @RequestMapping(value = "/getAllFileId")
    public List getAllFileId() {
     
        List list = new ArrayList<>();
        try {
            gridFSBucket.find().forEach(
                    (Block) gridFSFile -> System.out.println(gridFSFile.getId().toString()));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }

    /**
     * 获取fileId文件信息
     */
    @ResponseBody
    @RequestMapping(value = "/getSpecifyInfoFileByFileId")
    public GridFSDBFile getSpecifyInfoFileByFileId(@RequestParam(value = "fileId") String fileId) {
        try {
            return gridFS.findOne(fileId);
        }catch (Exception e){
            return null;
        }

    }




    /**
     * 通过fileId删除文件
     * @param fileId 文件ID
     * @return 成功为true, 失败为false
     */
    @ResponseBody
    @RequestMapping("/deleteFilesByObjectId")
    public boolean deleteFilesByObjectId(@RequestParam(value = "fileId") String fileId) {
        try {
            gridFSBucket.delete(new ObjectId(fileId));
            return true;
        } catch (Exception e) {
            return false;
        }

    }


}

4.4MongoDBConfig配置类

import com.mongodb.Mongo;
import com.mongodb.MongoClient;
import com.mongodb.gridfs.GridFS;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;


@Configuration
public class MongoDBConfig {

    @Bean
    public GridFS gridFS() {
        return new GridFS(mongo().getDB("db"));
    }

    @Bean
    public Mongo mongo() {
        return new MongoClient("localhost", 27017);
    }

}

这里遇到个小Bug(对我是)MongoClient mongoClient不能使用@Bean注解去实现IOC,只能通过在代码中

MongoClient mongoClient = new MongoClient("localhost", 27017);这样去生成...如果你知道请留言...到此就基本实现了需求。

顺便说一下,文件下载核心的就是通过文件Id获得输出流,也就是官网文档这句,然后把输出流放入response中就可以下载了。

gridFSBucket.downloadToStream(fileId, streamToDownloadTo);

我使用的方法是版本2.2以前的方法,因为我要获取文件对象中的metadata中的文件名和类型,新版是使用gridFSBucket ,可以参照下面这篇博客了解。也就是下面这段代码

String fileId = "5602de6e5d8bba0d6f2e45e4";
// 从Mongod中查找出一个文件,注意这里返回为com.mongodb.client.gridfs.model.GridFSFile类
GridFSFile gridFsdbFile = operations.findOne(new Query(Criteria.where("_id").is(fileId)));
if (gridFsdbFile != null) {
        // mongo-java-driver3.x以上的版本就变成了这种方式获取
        GridFSBucket bucket = GridFSBuckets.create(mongoDbFactory.getDb());
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        // 获取Mongodb中文件的缓存输出流
        bucket.downloadToStream(gridFsdbFile.getId(), baos);
        ...
} 
//spring-data-mongodb从2.0版本开始,其中GridFsOperations#findOne方法,返回类型为
//com.mongodb.client.gridfs.model.GridFSFile,不是再为com.mongodb.gridfs.GridFSDBFile类型。所
//以,这里就不得不用GridFSBucket来获取文件

4.5文件上传html

不能直接用url测试,也不能用IDEA的REST Client工具上传文件(至少我是不能),最好写一个网页前端文件上传界面,我还是附上吧QAQ(如果不能用就百度个)




    
    
    测试文件上传
    
    
    
    
    
    



    
	

五.总结

Ctrl +C吧

 

你可能感兴趣的:(Spring项目使用Mongodb中GridFS实现文件上传下载查找(附效果图))