GridFS

GridFS教程

一、GridFS简介

1.GridFS的作用

GridFS是用于存储和检索超过16M文档大小限制的文件的规范。GridFS不会将文件存储在单个文档中,而是将文件分成多个部分或大块。并将每个大块存储为单独的文档。

默认情况下,GridFS使用的默认块大小为255kb,也就是说除了最后一个块,GridFS会将文件分成255kb的块,而最后一块只有必要的大小。如果一个文件,不大于块大小仅具有最终块,仅使用所需的空间以及一些其他元数据。

2.GridFS是如何存储文件的

  • GridFS使用两个集合来存储文件,一个集合存储文件块,另一个集合存储文件元数据。

  • 当查询文件时,驱动程序将根据需要重新组装文件块。

  • 可以对GridFS存储的文件进行范围查询。也可以从文件的任意部分访问信息,比如跳到视频或音频文件的中间。

3.什么时候使用GridFS

  • 如果文件系统限制了目录中文件的数量,则可以使用GridFS来存储所需数量的文件。
  • 当您要访问大文件部分的信息而不必将整个文件加载到内存中时,可以使用GridFS来调用文件的某些部分,而无需将整个文件读入内存。
  • 当您想要使文件和元数据自动同步并跨多个系统和设施部署时,可以使用GridFS。使用地理上分散的副本集时,MongoDB可以自动将文件及其元数据分发到许多 mongod实例和设施。

如果文件均小于16 MB的限制,请考虑将每个文件存储在单个文档中,而不要使用GridFS。

4.GridFS的集合

4.1 存储二进制块的chunks

集合名: fs.chunks

集合中的每个文档代表一个单独的文件块,如下:
{ 
  “ _id”  : < ObjectId > ,# 块的唯一ObjectId
  “ files_id”  : < ObjectId > ,#在_id“父”的文件,如在指定的files 集合。
  “ n”  : < num > , #块的序列号。GridFS从0开始对所有块进行编号。
  “ data”  : < 二进制>  #块的有效载荷作为BSON Binary类型。
}
4.2 存储元数据的files

集合名:fs.files

files集合中的每个文档代表GridFS中的一个文件 。如下:
{ 
  “ _id”  : < ObjectId > , #该文档的唯一标识符。该_id是你选择的原始文档中的数据类型。
  “ length”  : < num > ,#文档的大小(以字节为单位)。
  “ chunkSize”  : < num > ,#每个块的大小(以字节为单位)。
  “ uploadDate”  : < 时间戳> ,#GridFS首次存储文档的日期。此值具有 Date类型。
  “ md5”  : < 哈希> ,
  “ filename”  : < 字符串> ,#可选的。GridFS文件的可读名称。
  “ contentType“  : < 字符串> ,
  ” aliases“  : < 字符串 数组>,
  “metadata”  : <任何> ,#元数据字段,可以是任何数据类型,并且可以包含您要存储的任何其他信息。如果希望向files 集合中的文档添加其他任意字段,请将其添加到元数据字段中的对象。
}

如果您需要分片GridFS数据存储,请使用chunks收集设置或作为分片键索引。

任何文件系统中的数据分为数据和元数据。数据是指普通文件中的实际数据,即文件的实际内容;而元数据指用来描述一个文件的特征的系统数据,诸如访问权限、文件拥有者以及文件数据块的分布信息(inode…)等等。在集群文件系统中,分布信息包括文件在磁盘上的位置以及磁盘在集群中的位置。用户需要操作一个文件必须首先得到它的元数据,才能定位到文件的位置并且得到文件的内容或相关属性。
文件的元数据有以下几项内容:

File   文件名
Size   文件大小(字节)
Blocks   文件使用的数据块总数
IO Block   数据块的大小
regular file:文件类型(常规文件) 
Device 设备编号 
Inode 文件所在的Inode
Links 硬链接次数
Access 权限
Uid 属主id/用户
Gid 属组id/组名
Access Time:简写为atime,表示文件的访问时间。当文件内容被访问时,更新这个时间 
Modify Time:简写为mtime,表示文件内容的修改时间,当文件的数据内容被修改时,更新这个时间。 
Change Time:简写为ctime,表示文件的状态时间,当文件的状态被修改时,更新这个时间,例如文件的链接数,大小,权限,Blocks数。

在linux系统下,使用stat(显示inode信息)命令可以查看一个文件的上述信息。

二、GridFS的命令行操作工具mongofiles

1.语法格式

mongofiles <选项> <命令> <文件名>

1) 选项。您可以使用这些选项中的一个或多个来控制的行为mongofiles。
2) 命令。使用以下命令之一确定的操作mongofiles。
3) 文件名可以是:本地文件系统上的文件名或GridFS对象。

2.应用案例

2.1 上传文件到GridFS
./mongofiles --port 27017 -d dbimg put /root/car01.jpg 
2.2 下载文件

根据文件名下载

./mongofiles --port 27017  -d dbimg get /root/car01.jpg --local /root/img/1.jpg

根据文件的objectid下载

./mongofiles --port 27017 get_id 'ObjectId("5e149750685a5f06e84877c4")' --local /root/img/2.jpg -d dbimg
2.3 查看文件

查看所有文件信息

./mongofiles --port 27017 -d dbimg list 

查看指定文件的信息

./mongofiles --port 27017 -d dbimg list filename
2.4 搜索文件

根据文件名搜索指定文件

./mongofiles --port 27017 -d dbimg search /root/car01.jpg
2.5 删除文件

根据文件名删除

./mongofiles --port 27017 -d dbimg delete /root/car01.jpg 

根据objectid删除

./mongofiles --port 27017 delete_id 'ObjectId("5b35153aaa1fc308053d8188")' /root/car01.jpg -d dbimg

三、Springbootdata操作GridFS

@SpringBootTest(classes = App.class)
@RunWith(SpringJUnit4ClassRunner.class)
public class TestMongofiles {

    @Autowired
    private MongoTemplate mongoTemplate;
    @Autowired
    private GridFsTemplate gridFsTemplate;

    // 上传文件
    @Test
    public void test0() throws FileNotFoundException {
        File file = new File("D:\\develop\\上课资料\\web_上\\html\\html资料\\img\\car05.jpg");
        FileInputStream fileInputStream = new FileInputStream(file);
        ObjectId objectId = gridFsTemplate.store(fileInputStream, "car.jpg", "img/jpeg");
        System.out.println(objectId.toString());
    }

    @Test
    public void test5() {
        Query query = new Query(Criteria.where("_id").is("5e149e946cff115a50224232"));
        // 查询一个文件
        GridFSFile gridFSFile = gridFsTemplate.findOne(query);
        ObjectId objectId = gridFSFile.getObjectId();
        System.out.println(objectId);
    }

    @Test
    public void test6() {
        Query query = new Query();
        // 查询所有文件
        GridFSFindIterable gridFSFiles = gridFsTemplate.find(query);
        for (GridFSFile gridFSFile : gridFSFiles) {
            System.out.println(gridFSFile.getObjectId());
        }
    }
    //下载文件

    @Test
    public void test1() throws IOException {
        //根据id查询文件
        GridFSFile gridFSFile = gridFsTemplate.findOne(new Query(Criteria.where("_id").is("5e14a3ec6cff115ee0d23206")));
        //打开下载流对象
        GridFSBucket gridFSBucket = GridFSBuckets.create(mongoTemplate.getDb());
        GridFSDownloadStream gridFSDownloadStream = gridFSBucket.openDownloadStream(gridFSFile.getObjectId());
        //创建GridFSResource,用于获取流对象
        GridFsResource gridFsResource = new GridFsResource(gridFSFile, gridFSDownloadStream);
        // 获取流中的数据
        InputStream inputStream = gridFsResource.getInputStream();
        File f1 = new File("D:\\test\\get.png");
        if (!f1.exists()) {
            f1.getParentFile().mkdirs();//递归创建父目录
        }
        FileOutputStream fileOutputStream = new FileOutputStream(f1);
        byte[] bytes = new byte[1025];
        int len = 0;
        while ((len = inputStream.read(bytes))!=-1) {
            fileOutputStream.write(bytes,0,len);
        }
        inputStream.close();
        fileOutputStream.close();


    }


    //删除文件
    @Test
    public void testDelFile() throws IOException {
        //根据文件id删除fs.files和fs.chunks中的记录
        gridFsTemplate.delete(Query.query(Criteria.where("_id").is("5e149e946cff115a50224232")));
    }
}

将mongoDb中的图片展示到前台页面

@RestController
@RequestMapping("/imgFile")
public class ImgFileController {
    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private GridFsTemplate gridFsTemplate;

    @RequestMapping("/show")
    public PictureBean show() throws IOException {
        Query query = new Query();
        query.addCriteria(Criteria.where("_id").is("5e14a3b66cff110864095cc7"));
        // 查询所有文件
        GridFSFile gridFSFile = gridFsTemplate.findOne(query);
        // 打开下载流对象
        GridFSBucket gridFSBucket = GridFSBuckets.create(mongoTemplate.getDb());
        GridFSDownloadStream gridFSDownloadStream = gridFSBucket.openDownloadStream(gridFSFile.getObjectId());
        //构建GridFSResources,用于获取文件的输入流对象
        GridFsResource gridFsResource = new GridFsResource(gridFSFile, gridFSDownloadStream);
        InputStream in = gridFsResource.getInputStream();
        System.out.println(gridFSFile.getObjectId());
        byte[] data = new byte[1024];
        ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
        int len = -1;
        try {
            while ((len = in.read(data)) != -1) {
                swapStream.write(data, 0, len);
            }
            in.close();
        } catch (IOException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

        BASE64Encoder encoder = new BASE64Encoder();
        String pictureBase = encoder.encode(swapStream.toByteArray()).trim();
        System.out.println(pictureBase);
        return new PictureBean(pictureBase);
    }
}

HTML

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/jquery-3.3.1.min.js"></script>
    <script>
        $(function () {
            $.ajax({
                url:"/imgFile/show",
                type:"post",
                success:function (result) {
                    console.log(result);
                    $('#img').attr("src","data:image/png;base64,"+result.imgEncode);
                }
            })
        })
    </script>
</head>
<body>
<img id="img" src="" alt="">
</body>
</html>
  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值