GridFS
Overview
在本指南中,您可以了解如何使用 GridFS 规范在 MongoDB 中存储和检索大文件。GridFS 将大文件分割为数据段,并将每个数据段存储为一个单独的文档。当您查询 GridFS 中的文件时,驱动程序会根据需要组合这些数据段。GridFS 的驱动程序实现是一个用来管理文件存储的操作和组织的抽象。
如果文件大小超过16 MB 的BSON文档大小限制,请使用GridFS 。 GridFS还可以帮助您访问权限文件,而无需将整个文件加载到内存中。要详细学习;了解GridFS是否适合您的使用案例,请参阅服务器手册中的 GridFS 。
GridFS 的工作原理
GridFS 在存储桶中组织文件,存储桶是一组包含文件数据段及其描述信息的MongoDB 集合。存储桶包含了以下集合:
chunks
,存储二进制文件数据块files
,存储文件元数据
当你创建新的 GridFS 存储桶时,驱动程序会创建前面的集合。除非指定不同的存储桶名称,否则默认存储桶名称 fs
将作为集合名称的前缀。驱动程序在第一次写操作期间创建新的 GridFS 存储桶。
驱动程序还会在每个集合上创建一个索引,以确保高效地检索文件和相关元数据。当索引尚不存在以及存储桶为空时,驱动程序会创建索引。要了解有关 GridFS 索引的更多信息,请参阅服务器手册中的 GridFS 索引。
使用 GridFS 存储文件时,驱动程序会将文件拆分成较小的数据段,每个数据段由 chunks
集合中的单独文档表示。它还会在 files
(文件)集合中创建一个文档,其中包含文件 ID、文件名以及其他文件元数据。如下图表展示了 GridFS 如何分割所上传的文件:
当检索文件时,GridFS 从指定的存储桶上的 files
(文件)集合中获取元数据,并使用这些信息从 chunks
(数据段)集合中的文档中重建文件。您可以将文件读取到内存中,或者将其输出到流。
GridFS 操作
以下各节描述如何执行 GridFS 操作:
创建 GridFS 存储桶
若要从 GridFS 存储或检索文件,请创建存储桶或获取对 MongoDB 数据库上现有存储桶的引用。要创建 GridFSBucket
实例,请在 Database
实例上调用 GridFSBucket()
方法,如以下代码所示:
db := client.Database("myDB") bucket := db.GridFSBucket()
注意
如果 GridFS 存储桶已经存在,则 GridFSBucket()
方法将返回该存储桶的引用,而不是实例化新的存储桶。
默认情况下,驱动程序将存储桶的名称设置为 fs
。要创建具有自定义名称的存储桶,请在 BucketOptions
实例上调用 SetName()
方法,如以下代码所示:
db := client.Database("myDB") bucketOpts := options.GridFSBucket().SetName("myCustomBucket") bucket := db.GridFSBucket(bucketOpts)
上传文件
您可以通过使用以下方式之一将文件上传到 GridFS 存储桶:
UploadFromStream()
,从输入流中读取OpenUploadStream()
,写入输出流
对于任一上传进程,您都可以通过创建UploadOptions
实例来指定配置信息。要查看选项的完整列表,请参阅 UploadOptions API文档。
使用一个输入流上传
要上传包含输入流的文件,请使用 UploadFromStream()
方法并包含以下参数:
文件名
io.Reader
实例,包括您打开的文件作为参数opts
参数,用来修改行为UploadFromStream()
如下代码示例将从一个名为 file.txt
的文件中读取内容,创建 opts
参数来设置文件元数据,并将内容上传到一个 GridFS 存储桶:
file, err := os.Open("home/documents/file.txt") uploadOpts := options.GridFSUpload().SetMetadata(bson.D{{"metadata tag", "first"}}) objectID, err := bucket .UploadFromStream( "file.txt", io.Reader(file), uploadOpts ) if err != nil { panic(err) } fmt.Printf("New file uploaded with ID %s", objectID)
New file uploaded with ID ...
使用输出流上传
要使用输出流上传文件,请使用 OpenUploadStream()
方法并包含以下参数:
文件名
opts
参数,用来修改行为OpenUploadStream()
如下代码示例将在一个 GridFS 存储桶上打开一个上传流,并在选项参数中设置每个数据块中的字节数。随后,它对 file.txt
的内容调用 Write()
方法,以便将其内容写入到流:
file, err := os.Open("home/documents/file.txt") if err != nil { panic(err) } // Defines options that specify configuration information for files // uploaded to the bucket uploadOpts := options.GridFSUpload().SetChunkSizeBytes(200000) // Writes a file to an output stream uploadStream, err := bucket.OpenUploadStream("file.txt", uploadOpts) if err != nil { panic(err) } fileContent, err := io.ReadAll(file) if err != nil { panic(err) } var bytes int if bytes, err = uploadStream.Write(fileContent); err != nil { panic(err) } fmt.Printf("New file uploaded with %d bytes written", bytes) // Calls the Close() method to write file metadata if err := uploadStream.Close(); err != nil { panic(err) }
检索文件信息
您可以检索 GridFS 存储桶的 files
集合中存储的文件元数据。files
集合中的每个文档都包含以下信息:
文件 ID
文件长度
最大数据块大小
上传日期和时间
文件名
metadata
文档,存储任何其他信息
要检索文件数据,请在 GridFSBucket
实例上调用 Find()
方法。您可以将查询过滤器作为参数传递给 Find()
,以仅匹配某些文件文档。
注意
您必须将查询筛选器传递给 Find()
方法。要检索 files
集合中的所有文档,请将空查询筛选器传递给 Find()
。
以下示例会检索 length
值大于 1500
的文档的文件名和长度:
filter := bson.D{{"length", bson.D{{"$gt", 1500}}}} cursor, err := bucket.Find(filter) if err != nil { panic(err) } type gridFSFile struct { Name string `bson:"filename"` Length int64 `bson:"length"` } var foundFiles []gridFSFile if err = cursor.All(context.TODO(), &foundFiles); err != nil { panic(err) } for _, file := range foundFiles { fmt.Printf("filename: %s, length: %d\n", file.Name, file.Length) }
下载文件
您可以通过以下方法之一下载 GridFS 文件:
DownloadToStream()
,将文件下载到输出流OpenDownloadStream()
,打开一个输入流
将文件下载到输出流
您可以通过使用 DownloadToStream()
方法将 GridFS 存储桶中的文件直接下载到输出流。DownloadToStream()
方法将文件 ID 和 io.Writer
实例作为参数。该方法下载指定文件 ID 的文件,并将其写入 io.Writer
实例。
以下示例下载文件并写入文件缓冲区:
id, err := primitive.ObjectIDFromHex("62f7bd54a6e4452da13b3e88") fileBuffer := bytes.NewBuffer(nil) if _, err := bucket.DownloadToStream(id, fileBuffer); err != nil { panic(err) }
将文件下载到输入流
可以使用 OpenDownloadStream()
方法通过输入流将 GridFS 存储桶中的文件下载到内存。OpenDownloadStream()
方法会将文件 ID 作为参数并返回一个输入流,您可以从中读取文件。
如下示例将一个文件下载到内存中并读取它的内容:
id, err := primitive.ObjectIDFromHex("62f7bd54a6e4452da13b3e88") downloadStream, err := bucket.OpenDownloadStream(id) if err != nil { panic(err) } fileBytes := make([]byte, 1024) if _, err := downloadStream.Read(fileBytes); err != nil { panic(err) }
重命名文件
可以使用 Rename()
方法更新存储桶中 GridFS 文件的名称。将文件 ID 值和新的 filename
值作为参数传递给 Rename()
。
如下示例将一个文件重命名为 "mongodbTutorial.zip"
:
id, err := primitive.ObjectIDFromHex("62f7bd54a6e4452da13b3e88") if err := bucket.Rename(id, "mongodbTutorial.zip"); err != nil { panic(err) }
删除文件
您可以使用 Delete()
方法从 GridFS 存储桶中删除文件。将文件 ID 值作为参数传入 Delete()
。
以下示例删除文件:
id, err := primitive.ObjectIDFromHex("62f7bd54a6e4452da13b3e88") if err := bucket.Delete(id); err != nil { panic(err) }
删除 GridFS 存储桶
您可以使用 Drop()
方法删除一个 GridFS 存储桶。
以下代码示例会删除 GridFS 存储桶:
if err := bucket.Drop(); err != nil { panic(err) }
其他资源
要了解有关 GridFS 和存储的更多信息,请参阅服务器手册中的以下页面:
API 文档
要进一步了解本指南所提及的方法和类型,请参阅以下 API 文档: