MongoDB GridFS介绍
GridFS 用于存储和恢复那些超过16M(BSON文件限制)的文件(如:图片、音频、视频等)。
GridFS 会将大文件对象分割成多个小的chunk(文件片段),一般为256k/个,每个chunk将作为MongoDB的一个文档(document)被存储在chunks集合中。
GridFS 用两个集合来存储一个文件:fs.files与fs.chunks。
每个文件的实际内容被存在chunks(二进制数据)中,和文件有关的meta数据(filename,content_type,还有用户自定义的属性)将会被存在files集合中。
go中使用
- 增加文件
// 输入文件名,将文件保存在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
}
- 完整代码测试
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
}