golang mongoDB GridFS查询 存储 删除文件

先讲一下 GridFS的作用

GridFS 用于存储和恢复那些超过16M(BSON文件限制)的文件(如:图片、音频、视频等),如果没有超过16m大小可以将数据保存在BSON数据中。 GridFS 也是文件存储的一种方式,但是它是存储在MonoDB的集合中。

GridFS 会将大文件对象分割成多个小的chunk(文件片段),一般为256k/个,每个chunk将作为MongoDB的一个文档(document)被存储在chunks集合中。

GridFS 用两个集合来存储一个文件:fs.files与fs.chunks。 每个文件的实际内容被存在chunks(二进制数据)中,和文件有关的meta数据(filename,content_type,还有用户自定义的属性)将会被存在files集合中。 官方文档中还有这么两句话: GridFS is useful not only for storing files that exceed 16 MB but also for storing any files for which you want access without having to load the entire file into memory. See also When to Use GridFS. GridFS是可以存储任何你想要存储的文件,不仅仅是那些超过16M文件,意思是什么文件都能存。

Furthermore, if your files are all smaller the 16 MB BSON Document Size limit, consider storing the file manually within a single document instead of using GridFS. You may use the BinData data type to store the binary data. 此外,如果您的文件全部小于16 MB bson文档大小限制,请考虑将文件手动存储在单个文档中,而不是使用gridfs。您可以使用bindata数据类型来存储二进制数据。

第一步:先用命令行的方式存储一下,方便演示,我选一个音乐21M大小 在windows 的mongoDB安装平台下:与mongo.exe,mongod.exe 所在目录存在一个mongofiles.exe 命令行的方式进入,执行下面命令就可以:

mongofiles.exe -h 127.0.0.1  -d gridfs put Test.mkv

意思是向127.0.0.1的数据库gridfs添加Test.mkv 视频文件 参数说明: –d 指定数据库 ,默认是fs,Mongofiles list –d testGridfs -u –p 指定用户名,密码 -h 指定主机 -port 指定主机端口 -c 指定集合名,默认是fs -t 指定文件的MIME类型,默认会忽略 查看一下。 使用mongoDB的数据库工具“MongoDB Compass”查看数据

数据库中增加一个gridfs数据库,里面多了2个集合,分别为fs.chunks或者fs.files

打开fs.files可以看到数据库中有2个文件一个叫做something.mp3 一个Test.mkv,Test.mkv是我刚刚上传的。 上传的数据存在fs.chunks中,文件信息存储在fs.files中。

现在开始用golang代码操作了: 下载刚才存储的视频:还原到本地 。我选一个something.mp3 进行下载。 package main

import (
    "fmt"
    "gopkg.in/mgo.v2"

    "log"
    "os"
    "io"
)

func main() {
    session, err := mgo.Dial("mongodb://127.0.0.1:27017")
    defer session.Close()
    if err != nil {
        fmt.Println(err)
        return
    }
    names, err := session.DatabaseNames();
    if err != nil {
        fmt.Println("未查询到数据库名字:", err)
    }
    fmt.Println(names)
    //通过文件名获取mp3
    file, err := session.DB("gridfs").GridFS("fs").Open("someThing.mp3")
    if err !=nil {
        fmt.Println(err)
        return
    }
    out, _ := os.OpenFile("E:\\test\\something.mp3.", os.O_CREATE, 0666)
    _,err = io.Copy(out, file)
    check(err)
    err = file.Close()
    check(err)
    //
    //b := make([]byte, 8192)
    //n, err := file.Read(b)
    //check(err)
    //fmt.Println(string(b))
    //check(err)
    //err = file.Close()
    //check(err)
    //fmt.Printf("%d bytes read\n", n)
}
func check(err error){
    log.Print(err)
}

运行结果:可以直接将something.mp3 下载到本地。

保存上传操作: 将something.mp3 改名字为 my.mp3 保存到gridfs

func upload(){
    session, err := mgo.Dial("mongodb://127.0.0.1:27017")
    defer session.Close()
    if err != nil {
        fmt.Println(err)
        return
    }
    names, err := session.DatabaseNames();
    if err != nil {
        fmt.Println("未查询到数据库名字:", err)
    }
    fmt.Println(names)
    //通过文件名创建mp3
    file, err := session.DB("gridfs").GridFS("fs").Create("my.mp3")
    if err !=nil {
        fmt.Println(err)
        return
    }
    out, _ := os.OpenFile("E:\\test\\something.mp3.", os.O_RDWR, 0666)
    _,err = io.Copy(file, out)
    check(err)
    err = file.Close()
    check(err)
    err=out.Close()
    check(err)
}

运行结果

文件的删除操作

//直接利用名字移除
err = session.DB("gridfs").GridFS("fs").Remove("my.mp3")
    if err !=nil {
        fmt.Println(err)
    }else {
        fmt.Print("刪除成功")
    }

文件的查询操作

func ReadAll()  {
    session, err := mgo.Dial("mongodb://127.0.0.1:27017")
    defer session.Close()
    if err != nil {
        fmt.Println(err)
        return
    }
    names, err := session.DatabaseNames();
    if err != nil {
        fmt.Println("未查询到数据库名字:", err)
    }
    fmt.Println(names)
    //通过文件名获取mp3
    gfs := session.DB("gridfs").GridFS("fs");
    iter := gfs.Find(nil).Iter()

    result:=new(fileinfo)
    for iter.Next(&result) {
        fmt.Println("一个一个输出:", result)
    }

}
type fileinfo struct {
    //文件大小
    LENGTH int32
    //md5
    MD5 string
    //文件名
    FILENAME string
}

func check(err error){
    log.Print(err)
}

运行结果: 一个一个输出: &{3963133 e58d3babaa101a57876c4b59945dd274 someThing.mp3} 一个一个输出: &{68113996 f79616b9e7dab89c9a0985349fd3ad10 Test.mkv}

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏较真的前端

Headless Testing入坑指南

22850
来自专栏刘望舒

Android解析WindowManager(二)Window的属性

前言 在上一篇文章我们学习了WindowManager体系,了解了Window和WindowManager之间的关系,这一篇我们接着来学习Window的属性。 ...

24680
来自专栏更流畅、简洁的软件开发方式

【开源】QuickPager ASP.NET2.0分页控件V2.0.0.6 修改了几个小bug,使用演示。

     由于项目里面还在使用vs2003,还没有使用新的分页控件,所以对新的分页控件的测试还很不到位,遗留了不少的bug,感谢网友试用提出宝贵意见。由于项目正...

22150
来自专栏24K纯开源

一款批量修改AE模板的工具

一、需求分析      对于视频后期剪辑及相关从业人员来说,AE(After Effects)模板效果是一个不错的开始点。在模板效果的基础上,可以很快的做出各种...

41370
来自专栏雪胖纸的玩蛇日常

Vue+koa2开发一款全栈小程序(9.图书详情页)

24810
来自专栏更流畅、简洁的软件开发方式

【自然框架】表单控件 之 一个表单修改多个表里的记录

      FormView 确实挺方便的,不过他也有几个小问题,只把FormView拖到页面里是不行的,还得再拽几个文本框、下拉列表框这一类的控件,还得布局。...

23760
来自专栏Hongten

python开发_tkinter_自己做的猜数字小程序

读到这篇文章[python 3.3下结合tkinter做的猜数字程序]的时候,就复制了代码,在自己机器上面跑了一下

17010
来自专栏Puppeteer学习

Headless Chrome:服务端渲染JS站点的一个方案【中篇】【翻译】防止重新渲染优化

24930
来自专栏海说

vue前端页面跳转参数传递及存储

不同页面间进行参数传递,实现方式有很多种,最简单最直接的方式就是在页面跳转时通过路由传递参数,如下所示。 路由传递参数 this.$router.push({ ...

61300
来自专栏Python、Flask、Django

Go语言学习之 - 简单的并发程序

10910

扫码关注云+社区

领取腾讯云代金券