MongoDB入门学习(二)GridFS、GridFS整合SpringBoot

news2024/11/18 20:24:25

文章目录

  • GridFS
    • GridFS简介
    • GridFS存储原理
  • GridFS整合SpringBoot
    • 新增store()
    • 查询与下载find()、findOne()
    • 删除delete()
  • Demo案例

GridFS

GridFS简介

GridFS是MongoDB的一个用来存储/获取大型数据(图像、音频、视频等类型的文件)的规范。相当于一个存储文件的文件系统,但它的数据存储在MongoDB的集合中。GridFS能存储超过文档大小(16MB)限制的文件。
GridFS将文件分解成块,将每块数据保存在不同的文档中,每块大小最大为255KB。

GridFS存储原理

GridFS使用两个集合(collection)存储文件。一个集合是chunks,用于存储文件内容的二进制数据,一个集合是files,用于存储文件的元数据。
GridFS是一种在MongoDB中存储大二进制文件的机制,使用GridFS的原因:

  1. 存储巨大的文件,如视频、图片等。
  2. 利用GridFS简化需求。
  3. GridFS会直接利用已经建立的复制或分片机制,故障恢复和扩展容易。
  4. GridFS可以避免用户上传内容的文件系统出现问题。
  5. GridFS不产生磁盘碎片。

GridFS使用俩个表来存储数据:

  1. files:包含元数据对象(如文件的名称、上传的时间)
  2. chunks:包含其他一些相关信息的二进制块
    在这里插入图片描述
    fs.files集合存储文件的元数据,以类的json文档格式存储。每在GridFS存储一个文件,则会在fs.files集合中生成一个文档。
    fs.filse集合中文档的存储内容如下:
{
	"_id": <ObjectId>,		//(必填)文档ID,唯一标识
	"chunkSize": <num>,		//(必填)chunk大小 256kb
	"uploadDate": <timestamp>,	//(必填)文件第一次上传时间
	"length": <num>,	//(必填)文件长度
	"md5": <string>,	//(必填)文件md5的值
	"filename": <string>,		//(可选)文件名
	"contentType":<string> ,	//(可选)文件的MIME类型
	"metadata": <dataObject>		//(可选)文件自定义的信息
}

fs.chunks集合存储文件内容的二进制数据,以类json格式文档形式存储。每在GridFS存储一个文件,GridFS就会将文件内容按照chunksize大小分成多个文件块,然后将文件按照类json格式存储到chunks集合中,每个文件块对应fs.chunk集合中一个文档。一个存储文件会对应一个到多个chunk文档。
fs.chunks集合中文档的存储内容如下:

{
	"_id": <ObjectId>,	// (必填)文档唯一表示
	"files_id": <ObjectId>,	//(必填)对应fs.files文档的ID
	"n": <num>,	// (必填)序号,表示文件的第几个chunk
	"data": <binary>	// (必填)文件二进制数据
}

GridFS整合SpringBoot

新增store()

@Autowired
private GridFsTemplate gridFsTemplate;
@Autowired
private GridFSBucket gridFSBucket;
@Test
public void test_insert() throws FileNotFoundException {
    File file = new File("G:\\test.txt");
    ObjectId objId = gridFsTemplate.store(new FileInputStream(file), "测试.txt", "txt");
    System.out.println(objId.toString());
}

查询与下载find()、findOne()

@Test
public void test_read() throws IOException {
    System.out.println("============ 查询所有文件 ==============");
    GridFSFindIterable files = gridFsTemplate.find(new Query());
    files.forEach(f -> {
        System.out.println(f.toString());
    });
    System.out.println("============ 根据ID查找文件 ==============");
    String fileId = "63b97c1c9b7cf822eeac502a";
    GridFSFile file = gridFsTemplate.findOne(Query.query(Criteria.where("_id").is(fileId)));
    System.out.println(file.toString());
    System.out.println("============ 查找到对应的文件,读取文件 ==============");
    GridFSDownloadStream stream = gridFSBucket.openDownloadStream(file.getObjectId());
    GridFsResource gridFsResource = new GridFsResource(file, stream);
    InputStream inputStream = gridFsResource.getInputStream();
    this.fileOutPut(inputStream, gridFsResource.getFilename());
}
private void fileOutPut(InputStream inputStream, String filename) throws IOException {
    File f1 = new File("G:\\test\\" + filename);
    if (f1.exists()) f1.getParentFile().mkdir();
    FileOutputStream fos = new FileOutputStream(f1);
    byte[] bytes = new byte[1024];
    int len = 0;
    while ((len = inputStream.read(bytes)) != -1) {
        fos.write(bytes, 0, len);
    }
    inputStream.close();
    fos.close();
}

删除delete()

 @Test
 public void test_delete(){
     String fileId = "63b97c1c9b7cf822eeac502a";
     gridFsTemplate.delete(Query.query(Criteria.where("_id").is(fileId)));
 }

Demo案例

package com.hx.demo1.controller;


import com.mongodb.client.gridfs.GridFSFindIterable;
import com.mongodb.client.gridfs.model.GridFSFile;
import org.bson.BsonValue;
import org.bson.types.ObjectId;
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.data.mongodb.gridfs.GridFsResource;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

/**
 * @author Huathy
 * @date 2023-01-08 00:19
 * @description
 */
@RestController
@RequestMapping(value = "file", method = {RequestMethod.GET, RequestMethod.POST})
public class FileController {
    @Autowired
    GridFsOperations gridFsOperations;

    /**
     * 上传文件
     * @param file
     * @return
     * @throws IOException
     */
    @RequestMapping(value = "upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public Map<String, ObjectId> insert(@RequestPart(value = "file") MultipartFile file) throws IOException {
        //开始时间
        long begin = System.nanoTime();
        Map<String, ObjectId> map = new HashMap<>();
        InputStream streamForUpload = file.getInputStream();
        ObjectId objectId = gridFsOperations.store(streamForUpload, file.getOriginalFilename(), file.getContentType(), "测试上传");
        //上传结束
        long time = System.nanoTime() - begin;
        System.out.println("本次上传共耗时: " + time);
        System.out.println("上传成功!文件名: " + file.getOriginalFilename() + ". 文件ID: " + objectId);
        map.put(file.getOriginalFilename(), objectId);
        return map;
    }

    /**
     * 获取所有文件的ID
     * @return
     */
    @RequestMapping("/allFiles")
    public ArrayList<Object> findAllFiles() {
        GridFSFindIterable gridFSFiles = gridFsOperations.find(new Query());
        ArrayList<Object> ids = new ArrayList<>();
        gridFSFiles.forEach(f -> {
            BsonValue bsonValue = f.getId();
            ids.add(bsonValue.toString());
        });
        return ids;
    }

    /**
     * 根据ID下载文件
     * @param id        mongoDB的文件ID
     * @param response
     * @return
     * @throws IOException
     */
    @RequestMapping("/download")
    public String download(String id, HttpServletResponse response) throws IOException {
        GridFSFile file = gridFsOperations.findOne(Query.query(Criteria.where("_id").is(id)));
        if (file != null) {
            GridFsResource resource = gridFsOperations.getResource(file);
            response.reset();
            response.setContentType(resource.getContentType());
            response.setHeader("Content-Disposition", "attachment;filename=" + resource.getFilename());
            ServletOutputStream ops = response.getOutputStream();
            InputStream ips = resource.getInputStream();
            int len = 0;
            byte[] bytes = new byte[1024];
            while ((len = ips.read(bytes)) != -1) {
                ops.write(bytes, 0, len);
            }
            ips.close();
            ops.close();
            return resource.getContentType();
        }
        throw new RuntimeException("没有找到相关文件");
    }

    /**
     * 删除文件
     * @param id    mongodb的文件ID
     * @return
     */
    @GetMapping("/delete")
    public String deleteFile(String id){
        gridFsOperations.delete(Query.query(Criteria.where("_id").is(id)));
        return "delete success";
    }

}

测试结果:
在这里插入图片描述在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/148137.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java中创建不可变集合、Stream流、异常体系、日志框架

创建不可变集合、Stream流、异常体系、日志框架创建不可变集合什么是不可变集合&#xff1f;为什么要创建不可变集合&#xff1f;如何创建不可变集合&#xff1f;不可变集合的特点&#xff1f;Stream流Stream流的概述Stream流的获取Stream流的常用API&#xff08;中间操作方法&…

Index Tree(树状数组)

1、引入 线段树解决的是 区间查询 和 区间更新 的问题&#xff0c; O(logn)O(logn)O(logn) 复杂度。 人为规定&#xff1a;数组下标从 1 开始。 如果要计算数组某个范围 L 到 R 的累加和&#xff0c;那么可以准备一个前缀和数组 help&#xff0c;得到前缀和数组后&#xff0…

【寒假每日一题】洛谷 P6263 [COCI2014-2015#3] STROJOPIS

题目链接&#xff1a;P6263 [COCI2014-2015#3] STROJOPIS - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题目描述 正确的打字正成为文化的重要组成部分。如果你仍然没有使用所有的十根手指来打字&#xff0c;你必须重新学习打字——然后你会打字更快&#xff0c;感觉更舒适…

Web进阶:Day1 字体图标、平面转换、空间转换、动画

Web进阶&#xff1a;Day1 Date: October 3, 2022 Summary: 字体图标、平面转换、空间转换、动画 字体图标 字体图标 字体图标展示的是图标&#xff0c;本质是字体 处理简单的、颜色单一的图片 注&#xff1a;复杂的用CSS精灵&#xff0c;简单的用字体图标 字体图标的优点&…

Verilog语法笔记(夏宇闻第三版)-条件语句

目录 if_else语句&#xff1a; 五点说明&#xff1a; case语句&#xff1a; 真值表&#xff1a; ​例&#xff1a; ​由于使用条件语句不当在设计中生成了原本没想到有的锁存器&#xff1a; if_else语句&#xff1a; if语句是用来判定所给定的条件是否满足&#xff0c;…

(十四)面向对象的三大特征

目录 前言: 一、面向对象三大特征之一:封装 二、面向对象三大特征之二:继承 三、面向对象三大特征之三:多态 前言: 面向对象的三大特征:封装、继承、多态。 一、面向对象三大特征之一:封装 1.概述: 封装是把过程和数据包围起来&#xff0c;对数据的访问只能通过已定义的接口…

使用Idea编码常用的28种技巧方式

一丶列表: 1丶查看代码历史版本 2丶调整idea的虚拟内存&#xff1a; 3丶idea设置成eclipse的快捷键 4丶设置提示词忽略大小写 5丶关闭代码检查 6丶设置文档注释模板 7丶显示方法分隔符 8丶设置多行tab 9丶快速匹配方法的大括号位置 10丶代码结尾补全 11丶模糊搜索方法 12丶预览…

用 Python selenium爬取股票新闻并存入mysql数据库中带翻页功能demo可下载

用 Python selenium爬取实时股票新闻并存入mysql数据库中1.分析需求2.创建表3.分析需要爬取的网页内容4.python里面selenium进行爬虫操作1.添加包2.连接数据库3.selenium爬虫前配置4.对股票新闻内容爬取并存入mysql中5.翻页功能6.运行程序首先我们先明确我们的主要目标就是要爬…

5、SySeVR复现——Data preprocess(上)

目录 1、环境 2、生成切片对应的hash 3、获取要删除的切片位置信息 4、对切片进行token化 1、环境 从数据预处理开始&#xff0c;操作系统&#xff1a;windows 10 &#xff0c;软件&#xff1a;pycharm 注&#xff1a;对官方提供的文件&#xff0c;做了一些改动&#xff0c…

插槽 slot

文章目录一、什么是插槽二、插槽内容三、渲染作用域四、默认内容五、具名插槽六、作用域插槽一、什么是插槽 我们使用 <slot> 作为一个占位符&#xff0c;父组件就可以把要传递的内容显示到占位符所在位置上&#xff0c;提高组件使用的灵活性。 二、插槽内容 父组件向…

安信可VC系列语音识别的使用教程

安信可VC-02语音识别的应用&#xff0c;本篇只讲述在Windows系统下的应用。Linux下的请参考官方文档介绍和说明。 1-安信可VC-02离线语音识别简介 VC系列模组是我司开发的一款AI离线语音识别的产品&#xff0c;主芯片是云知声推出的离线语音识别芯片锋鸟M(US516P6)&#xff0c…

Redis基础语法和SpringBoot集成使用

在初期&#xff0c;已经讲述了Redis安装问题。现在正式进入Redis的入门阶段。 Redis客户端 命令行客户端 redis-cli [options] [commands]常用到的 options 有&#xff1a; -h 127.0.0.1: 指定要连接的Redis的IP地址【默认127.0.0.1】-p 6379: 指定连接Redis的端口【默认63…

jenkins前端页面自动运维值yarn编译运行项目

配置步骤如下 首先需要在系统管理中心安装node相关插件 安装完成之后&#xff0c;在系统管理——>全局工具配置——>NodeJS 点击新增Nodejs 此处自定义别名&#xff0c;我这里是Nodejs16&#xff0c;取消自动安装前面的复选框&#xff0c;下方选择我们的nodejs安装目录&…

云服务器定时执行python脚本

文章目录前言crontab简介基本语法定时任务具体内容python 脚本定时任务前言 在服务器上定时执行任务有两种方式&#xff0c;一种是at定时任务&#xff0c;一种是crond任务调度&#xff0c;at命令是一次性定时计划任务&#xff0c;at的守护进程 atd会以后台模式运行&#xff0c…

Spring注解之@validated使用

概念 spring-boot中可以用validated来校验数据&#xff0c;如果数据异常则会统一抛出异常&#xff0c;方便异常中心统一处理。 注解源码&#xff1a; Validated 作用在类、方法和参数上 Target({ElementType.TYPE, ElementType.METHOD, ElementType.PARAMETER}) Retention(…

python初级教程十一 urllib

urllib Python urllib 库用于操作网页 URL&#xff0c;并对网页的内容进行抓取处理。 本文主要介绍 Python3 的 urllib。 urllib 包 包含以下几个模块&#xff1a; urllib.request - 打开和读取 URL。 urllib.error - 包含 urllib.request 抛出的异常。 urllib.parse - 解…

【Python入门指北】操作数据库

文章目录一、1.数据库2.练手案例二、redis数据库一、 1.创建一个数据库 [guanmaster1 ~]$ mysql -uroot -p123456 mysql: [Warning] Using a password on the command line interface can be insecure. Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL…

Apache IoTDB PMC 乔嘉林荣获 2022 杰出开源贡献者|开源技术强大,开源文化活跃...

2022 年 12 月 29 日至 30 日&#xff0c;2022 木兰峰会正式召开&#xff0c;会上发布了中国开源云联盟 2022 年度评选名单。本次评审专家包括数十位开源领域专家、社区领袖、科研院所专家&#xff0c;共评选出杰出开源贡献者 3 人。其中&#xff0c;清华大学助理研究员、博士后…

【QT开发笔记-基础篇】| 第五章 绘图QPainter | 5.16 完结和后续:《Qt开发专题-自定义控件》

本节对应的视频讲解&#xff1a;B_站_视_频 https://www.bilibili.com/video/BV1NW4y1K7eL 1. 为什么需要自定义控件 绘图最大的一个应用场景就是自定义控件&#xff0c;Qt 本身提供的一些控件是有限的&#xff0c;并且它提供的一些控件很可能不满足我们的需要 这种情况下&a…

pygame - 图片移动优化

目录 一、优化过程分析 1、pygame - 图片移动中图片移动模式 2、优化过程 二、代码段 1、附注释 2、无注释 三、效果展示 一、优化过程分析 1、pygame - 图片移动中图片移动模式 按一次方向键&#xff0c;图片移动一小步&#xff1b; 若需要一直往某个方向移动&…