先讲一下 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 readn", 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}