A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© longxf_sjz 中级黑马   /  2019-10-19 10:52  /  1072 人查看  /  0 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

一 简介
    GridFS是MongoDB中存储和查询超过BSON文件大小限制(16M)的规范,不像BSON文件那样在一个单独的文档中存储文件,GridFS将文件分成多个块,每个块作为一个单独的文档。默认情况下,每个GridFS块是255kB,意味着除了最后一个块之外(根据剩余的文件大小),文档被分成多个255kB大小的块存储。    GridFS使用两个集合保存数据,一个集合        存储文件块,另外一个存储文件元数据。当从GridFS中获取文件时,MongoDB的驱动程序负责将多个块组装成完整文件,你可以通过GridFS进行范围查询,可以访问文件的任意部分        (例如跳到视频文件或者音频文件的任意位置)。无论是超过16M的文件和其他文件,只要存在访问时不想加载整个文件的场景存在,GridFS就有帮助。


二 应用场景
    在MongoDB中,使用GridFS存储超过16M的文件(BSON文件不能超过16M)。在某些情况下,MongoDB存储大文件会比操作系统的文件系统更高效:
        1. 如果你的文件系统限制目录下文件的个数,可以使用MongoDB在目录下存储任意多的文件。
        2. 访问大数据文件时,不想一次加载而是分段访问。
        3. 在多个系统间实现文件和元数据同步。
        对文件进行原子更新时,MongoDB不适合,不能支持对文件多个块更新操作的原子性;如果确有需要,也可以通过在元数据中指定当前版本来变通实现。        如果你的文件都小于16M,应该考虑使用每个文件存一个独立文档的方式来取代GridFS,可以使用BinData类型来存储二进制数据(也可以使用GridFS,需要修改chunk大小,避免小文件        被拆分,需要进行测试和比较性能)。


三 存储管理
    MongodB使用两个集合来存储GridFS文件,一个是fs.files,另一个是fs.chunks。
        fs.files这个集合中存储的是每一个上传到数据库的文档的信息。
        fs.chunks这个集合存储的是上传文件的内容。一个chunk相当于一个文档(大文件被拆分成多个有序的chunk)。
        GridFS中的bucket这个概念指代的是fs.files和fs.chunks的组合。
       
四 基于spring boot,实现GridFS的基本操作。
[Java] 纯文本查看 复制代码
@RestController
    @RequestMapping("/api")
    public class GridFSApi {
     private static Logger LOGGER = Logger.getLogger(GridFSApi.class);
     @Autowired
     private GridFsTemplate gridFsTemplate;
 
     @RequestMapping(value = "/save", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
     public Response save(@RequestParam(value = "file", required = true) MultipartFile file) {
 
         LOGGER.info("Saving file..");
         DBObject metaData = new BasicDBObject();
         metaData.put("createdDate", new Date());
 
         String fileName = UUID.randomUUID().toString();
 
         LOGGER.info("File Name: " + fileName);
 
         InputStream inputStream = null;
         try {
             inputStream = file.getInputStream();
             gridFsTemplate.store(inputStream, fileName, "image", metaData);
             LOGGER.info("File saved: " + fileName);
         } catch (IOException e) {
             LOGGER.error("IOException: " + e);
             throw new RuntimeException("System Exception while handling request");
         }
         LOGGER.info("File return: " + fileName);
         return new Response(fileName);
     }
 
     @RequestMapping(value = "/get", method = RequestMethod.GET, produces = MediaType.IMAGE_JPEG_VALUE)
     public byte[] get(@RequestParam(value = "fileName", required = true) String fileName) throws IOException {
         LOGGER.info("Getting file.." + fileName);
         List<GridFSDBFile> result = gridFsTemplate
                 .find(new Query().addCriteria(Criteria.where("filename").is(fileName)));
         if (result == null || result.size() == 0) {
             LOGGER.info("File not found" + fileName);
             throw new RuntimeException("No file with name: " + fileName);
         }
         LOGGER.info("File found " + fileName);
         return IOUtils.toByteArray(result.get(0).getInputStream());
     }
 
     @RequestMapping(value = "/delete", method = RequestMethod.DELETE)
     public void delete(@RequestParam(value = "fileName", required = true) String fileName) {
         LOGGER.info("Deleting file.." + fileName);
         gridFsTemplate.delete(new Query().addCriteria(Criteria.where("filename").is(fileName)));
         LOGGER.info("File deleted " + fileName);
     }
 }


0 个回复

您需要登录后才可以回帖 登录 | 加入黑马