Go操作mongoDB GridFS增删查

MongoDB GridFS介绍

GridFS 用于存储和恢复那些超过16M(BSON文件限制)的文件(如:图片、音频、视频等)。

GridFS 会将大文件对象分割成多个小的chunk(文件片段),一般为256k/个,每个chunk将作为MongoDB的一个文档(document)被存储在chunks集合中。
GridFS 用两个集合来存储一个文件:fs.files与fs.chunks。
每个文件的实际内容被存在chunks(二进制数据)中,和文件有关的meta数据(filename,content_type,还有用户自定义的属性)将会被存在files集合中。
GridFS文件内容

 fs.files 集合
fs.chunks 集合

go中使用

  1. 增加文件
// 输入文件名,将文件保存在MongoDB GridFS中,返回文件ID和错误码
func SaveFile(filename string) (fileId string, err error) {
    // 连接数据库
    session, err := mgo.Dial("mongodb://root:guoke3915@127.0.0.1:3717/admin")
    defer session.Close()
    if err != nil {
        fmt.Println(err)
        return
    }

    // 获取Test库
    db := session.DB("Test")

    // 在file前缀的GridFS中创建新文件
    file, err := db.GridFS("file").Create(filename)
    if err != nil {
        return
    }
    defer file.Close()

    // 读取文件内容
    data, err := os.OpenFile(filename, os.O_RDWR, 0666)
    if err != nil {
        return
    }
    defer data.Close()

    // 写入GridFS文件,这里也可以直接用[]byte字节流的文件
    _, err = io.Copy(file, data)
    if err != nil {
        return
    }

    // 以字符串形式返回文件ID
    fileId = file.Id().(bson.ObjectId).Hex()
    return
}
  1. 查询文件
// 输入数据库中文件ID和要保存的文件名,将数据库在文件存回本地,返回错误码
func LoadFile(fileId, filename string) (err error) {
    // 连接数据库
    session, err := mgo.Dial("mongodb://root:guoke3915@127.0.0.1:3717/admin")
    defer session.Close()
    if err != nil {
        fmt.Println(err)
        return
    }

    // 获取Test库
    db := session.DB("Test")

    // 通过文件名获取文件,文件名不唯一,如果存在同名的,返回最后上传的那一个
    // file, err := db.GridFS("file").Open(filename)
    // 通过文件ID获取文件,因为文件ID是唯一的
    file, err := db.GridFS("file").OpenId(bson.ObjectIdHex(fileId))
    if err != nil {
        return
    }
    defer file.Close()

    // 读取文件内容
    data, err := os.OpenFile(filename, os.O_CREATE, 0666)
    if err != nil {
        return
    }
    defer data.Close()

    // 将数据写入文件
    _, err = io.Copy(data, file)
    if err != nil {
        return
    }

    return
}
  1. 删除文件
// 删除文件,输入文件ID
func RemoveFile(fileId string) (err error) {
    // 连接数据库
    session, err := mgo.Dial("mongodb://root:guoke3915@127.0.0.1:3717/admin")
    defer session.Close()
    if err != nil {
        fmt.Println(err)
        return
    }

    // 获取Test库
    db := session.DB("Test")

    // 如果是文件名删,则删除所有同名的文件
    // err = db.GridFS("file").Remove(filename)
    // 通过文件ID删除文件
    err = db.GridFS("file").RemoveId(bson.ObjectIdHex(fileId))
    return
}
  1. 完整代码测试
package main

import (
    "fmt"
    "gopkg.in/mgo.v2"
    "gopkg.in/mgo.v2/bson"
    "io"
    "os"
)

func main() {
    fileId, err := SaveFile("test.txt")
    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Println(fileId)

    err = LoadFile(fileId, "test1.txt")
    if err != nil {
        fmt.Println(err)
        return
    }

    err = RemoveFile(fileId)
    if err != nil {
        fmt.Println(err)
        return
    }
}

// 输入文件名,将文件保存在MongoDB GridFS中,返回文件ID和错误码
func SaveFile(filename string) (fileId string, err error) {
    // 连接数据库
    session, err := mgo.Dial("mongodb://root:guoke3915@127.0.0.1:3717/admin")
    defer session.Close()
    if err != nil {
        fmt.Println(err)
        return
    }

    // 获取Test库
    db := session.DB("Test")

    // 在file前缀的GridFS中创建新文件
    file, err := db.GridFS("file").Create(filename)
    if err != nil {
        return
    }
    defer file.Close()

    // 读取文件内容
    data, err := os.OpenFile(filename, os.O_RDWR, 0666)
    if err != nil {
        return
    }
    defer data.Close()

    // 写入GridFS文件,这里也可以直接用[]byte字节流的文件
    _, err = io.Copy(file, data)
    if err != nil {
        return
    }

    // 以字符串形式返回文件ID
    fileId = file.Id().(bson.ObjectId).Hex()
    return
}

// 输入数据库中文件ID和要保存的文件名,将数据库在文件存回本地,返回错误码
func LoadFile(fileId, filename string) (err error) {
    // 连接数据库
    session, err := mgo.Dial("mongodb://root:guoke3915@127.0.0.1:3717/admin")
    defer session.Close()
    if err != nil {
        fmt.Println(err)
        return
    }

    // 获取Test库
    db := session.DB("Test")

    // 通过文件名获取文件,文件名不唯一,如果存在同名的,返回最后上传的那一个
    // file, err := db.GridFS("file").Open(filename)
    // 通过文件ID获取文件,因为文件ID是唯一的
    file, err := db.GridFS("file").OpenId(bson.ObjectIdHex(fileId))
    if err != nil {
        return
    }
    defer file.Close()

    // 读取文件内容
    data, err := os.OpenFile(filename, os.O_CREATE, 0666)
    if err != nil {
        return
    }
    defer data.Close()

    // 将数据写入文件
    _, err = io.Copy(data, file)
    if err != nil {
        return
    }

    return
}

// 删除文件,输入文件ID
func RemoveFile(fileId string) (err error) {
    // 连接数据库
    session, err := mgo.Dial("mongodb://root:guoke3915@127.0.0.1:3717/admin")
    defer session.Close()
    if err != nil {
        fmt.Println(err)
        return
    }

    // 获取Test库
    db := session.DB("Test")

    // 如果是文件名删,则删除所有同名的文件
    // err = db.GridFS("file").Remove(filename)
    // 通过文件ID删除文件
    err = db.GridFS("file").RemoveId(bson.ObjectIdHex(fileId))
    return
}
0%