使用GridFS存储大文件
Overview
在本指南中,您可以学习;了解如何使用GridFS在MongoDB中存储和检索大文件。 GridFS规范描述了如何在存储文件时将文件分割为数据段,并在检索文件时重新组合文件。 GridFS的Scala驱动程序实施是一个用于管理文件存储的操作和组织的抽象。
如果文件大小超过16 MB 的BSON文档大小限制,请使用GridFS 。 有关GridFS是否适合您的使用案例的更多详细信息,请参阅MongoDB Server手册中的 GridFS 。
以下部分描述了 GridFS 操作以及如何执行这些操作。
GridFS 的工作原理
GridFS 在存储桶中组织文件,存储桶是一组包含文件数据段及其描述信息的MongoDB 集合。存储桶包含以下集合,使用 GridFS 规范中定义的约定命名:
chunks
集合存储二进制文件数据段。files
集合存储文件元数据。
当您创建新的GridFS存储桶时,驾驶员会创建fs.chunks
和fs.files
集合,除非您在GridFSBucket()
构造函数中指定不同的名称。该驾驶员还会在每个集合上创建一个索引,以确保有效检索文件和相关元数据。如果GridFS存储桶不存在,则驾驶员仅在执行第一次写入操作时才会创建该存储桶。仅当索引不存在且存储桶为空时,驾驶员才会创建索引。有关GridFS索引的更多信息,请参阅MongoDB Server手册中的GridFS索引。
使用 GridFS 存储文件时,驱动程序会将文件拆分成较小的数据块,每个数据块由 chunks
集合中的单独文档表示。它还在 files
集合中创建文档,其中包含文件 ID、文件名和其他文件元数据。您可以从内存或数据流上传文件。请参阅下图,了解 GridFS 在上传到存储桶时如何拆分文件。
在检索文件时,GridFS 从指定存储桶上的 files
集合中获取元数据,并使用该信息通过 chunks
集合中的文档重建文件。您可以将文件读取到内存中,或者将其输出到流。
创建 GridFS 存储桶
要从 GridFS 存储或检索文件,请调用GridFSBucket()
构造函数并传入MongoDatabase
实例,以创建 GridFS 存储桶。 您可以使用GridFSBucket
实例对存储桶中的文件调用读取和写入操作。
val bucket = GridFSBucket(database)
要使用默认名称 fs
以外的默认定义名称创建或引用存储桶,请将存储桶名称作为第二个参数传递给 GridFSBucket()
构造函数,如以下示例所示:
val filesBucket = GridFSBucket(database, "files")
上传文件
GridFSBucket.uploadFromObservable()
方法读取Observable[ByteBuffer]
的内容并将其保存到GridFSBucket
实例中。
您可以使用GridFSUploadOptions
类型来配置数据段大小或包含其他元数据。
以下示例将 Observable[ByteBuffer]
的内容上传到 GridFSBucket
:
// Get the input stream val observableToUploadFrom = Observable( Seq(ByteBuffer.wrap("MongoDB Tutorial".getBytes(StandardCharsets.UTF_8))) ) // Create some custom options val options = new GridFSUploadOptions() .chunkSizeBytes(358400) .metadata(Document("type" -> "presentation")) // Upload the file val fileIdObservable = filesBucket.uploadFromObservable("mongodb-tutorial", observableToUploadFrom, options) val fileId = Await.result(fileIdObservable.toFuture(), Duration(10, TimeUnit.SECONDS)) println(s"File uploaded with id: ${fileId.toHexString}")
检索文件信息
在本部分中,您可以了解如何检索存储在 GridFS 存储桶的 files
集合的文件元数据。元数据包含所引用文件的相关信息,包括:
文件的
_id
文件的名称
文件的长度/大小
上传日期和时间
您可以在其中存储任何其他信息的
metadata
文档
要学习;了解有关可从files
集合检索的字段的更多信息,请参阅MongoDB Server手册中的GridFS文件集合文档。
要从GridFS存储桶检索文件,请对 GridFSBucket
实例调用 find()
方法。以下代码示例从GridFS存储桶中的所有文件中检索并打印文件元数据:
val filesObservable = filesBucket.find() val results = Await.result(filesObservable.toFuture(), Duration(10, TimeUnit.SECONDS)) results.foreach(file => println(s" - ${file.getFilename}"))
要学习;了解有关查询MongoDB 的更多信息,请参阅 检索数据。
下载文件
downloadToObservable()
方法返回一个Observable[ByteBuffer]
,用于从MongoDB读取内容。
要通过文件_id
下载文件,请将_id
传递给该方法。 以下示例通过文件_id
下载文件:
val downloadObservable = filesBucket.downloadToObservable("<example file ID>") val downloadById = Await.result(downloadObservable.toFuture(), Duration(10, TimeUnit.SECONDS))
如果您不知道文件的 _id
,但知道文件名,则可以将文件名传递给 downloadToObservable()
方法。以下示例下载名为 mongodb-tutorial
的文件:
val downloadObservable = filesBucket.downloadToObservable("mongodb-tutorial") val downloadById = Await.result(downloadObservable.toFuture(), Duration(10, TimeUnit.SECONDS))
注意
如果多个文档具有相同的 filename
值, GridFS将获取具有给定名称(由 uploadDate
字段确定)的最新文件。
重命名文件
使用 rename()
方法更新存储桶中 GridFS 文件的名称。您必须用文件的 _id
字段而不是文件名来指定要重命名的文件。
如下示例将一个文件重命名为 mongodbTutorial
:
val renameObservable = filesBucket.rename("<example file ID>", "mongodbTutorial") Await.result(renameObservable.toFuture(), Duration(10, TimeUnit.SECONDS))
注意
rename()
方法一次仅支持更新一个文件的名称。 要重命名多个文件,请从存储桶中检索与文件名匹配的文件列表,从要重命名的文件中提取_id
字段,然后将每个值分别传递给rename()
方法。
删除文件
使用 delete()
方法从存储桶中删除文件的集合文档和关联的数据段。您必须用文件的 _id
字段而不是文件名来指定文件。
以下示例通过 _id
删除文件:
val deleteObservable = filesBucket.delete("<example file ID>") Await.result(deleteObservable.toFuture(), Duration(10, TimeUnit.SECONDS))
注意
delete()
方法一次仅支持删除一个文件。 要删除多个文件,请从存储桶中检索文件,提取要删除的文件中的_id
字段,然后将每个值分别传递给delete()
方法。
API 文档
要学习;了解有关使用GridFS存储和检索大文件的更多信息,请参阅以下API文档: