GridFS
概述
在本指南中,您可以了解如何使用GridFS在MongoDB中存储和检索大文件。GridFS是一个规范,它描述了如何在存储期间将文件分割成块,并在检索期间重新组合它们。GridFS的驱动程序实现管理文件存储的操作和组织。
如果您的文件大小超过了16兆字节的BSON文档大小限制,请使用GridFS。有关GridFS是否适合您的用例的更多详细信息,请参阅GridFS服务器手册页.
导航以下部分,以了解更多关于GridFS操作和实现的信息
如何GridFS工作
GridFS 将文件组织在 存储桶 中,这是一个包含文件块和描述性信息的 MongoDB 集合组。存储桶包含以下集合,名称遵循 GridFS 规范中定义的约定
以下
chunks
集合存储二进制文件块。files
集合存储文件元数据。
创建新的 GridFS 存储桶时,驱动程序会创建 chunks
和 files
集合,默认使用 fs
作为前缀,除非指定了不同的名称。驱动程序还会在每个集合上创建索引,以确保文件和相关元数据的有效检索。如果存储桶不存在,驱动程序仅在第一次写入操作时创建 GridFS 存储桶。如果索引不存在且存储桶为空,驱动程序才会创建索引。有关 GridFS 索引的更多信息,请参阅服务器手册页面 GridFS 索引。
使用 GridFS 存储文件时,驱动程序会将文件拆分为更小的部分,每个部分由 chunks
集合中的一个单独文档表示。它还会在 files
集合中创建一个文档,其中包含唯一的文件 ID、文件名和其他文件元数据。您可以从内存或从流中上传文件。以下图解描述了 GridFS 在上传到存储桶时如何分割文件

检索文件时,GridFS 从指定存储桶的 files
集合中获取元数据,并使用该信息从 chunks
集合的文档中重建文件。您可以将文件读入内存或将输出输出到流中。
创建 GridFS 存储桶
创建一个存储桶或获取现有存储桶的引用以开始从 GridFS 存储或检索文件。创建一个 GridFSBucket
实例,将数据库作为参数传递。然后您可以使用 GridFSBucket
实例对存储桶中的文件进行读写操作
const db = client.db(dbName); const bucket = new mongodb.GridFSBucket(db);
将存储桶名称作为 create()
方法的第二个参数传递,以创建或引用具有除默认名称 fs
之外的自定义名称的存储桶,如下例所示
const bucket = new mongodb.GridFSBucket(db, { bucketName: 'myCustomBucket' });
获取更多信息,请参阅 GridFSBucket API 文档。
上传文件
使用 GridFSBucket
中的 openUploadStream()
方法为指定的文件名创建上传流。您可以使用 pipe()
方法将 Node.js 读取流连接到上传流。openUploadStream()
方法允许您指定配置信息,例如文件块大小和其他作为元数据存储的字段/值对。
以下示例展示了如何将表示为变量 fs
的 Node.js 读取流管道连接到 GridFSBucket
实例的 openUploadStream()
方法。
fs.createReadStream('./myFile'). pipe(bucket.openUploadStream('myFile', { chunkSizeBytes: 1048576, metadata: { field: 'myField', value: 'myValue' } }));
请参阅openUploadStream() API 文档获取更多信息。
检索文件信息
在本节中,您可以了解如何从 GridFS 桶的 files
集合中检索存储的文件元数据。元数据包含有关引用的文件的信息,包括
文件的
_id
文件名
文件的长度/大小
上传日期和时间
一个
metadata
文档,您可以在此存储其他任何信息
在 GridFSBucket
实例上调用 find()
方法以从 GridFS 桶中检索文件。该方法返回一个 FindCursor
实例,您可以通过它访问结果。
以下代码示例向您展示了如何从 GridFS 桶中的所有文件中检索并打印文件元数据。在从 FindCursor
可迭代对象检索结果的不同方法中,以下示例使用 for await...of
语法显示结果
const cursor = bucket.find({}); for await (const doc of cursor) { console.log(doc); }
find()
方法接受各种查询规范,可以与其他方法如 sort()
、limit()
和 project()
结合使用。
有关本节中提到的类和方法的更多信息,请参阅以下资源
下载文件
您可以使用来自GridFSBucket
的openDownloadStreamByName()
方法从您的MongoDB数据库中下载文件,以创建一个下载流。
以下示例展示了如何将存储在filename
字段中的文件名引用的文件下载到您的当前工作目录。
bucket.openDownloadStreamByName('myFile'). pipe(fs.createWriteStream('./outputFile'));
注意
如果有多个文档具有相同的filename
值,GridFS将流式传输具有给定名称的最新文件(由uploadDate
字段确定)。
或者,您可以使用接受文件_id
字段作为参数的openDownloadStream()
方法。
bucket.openDownloadStream(ObjectId("60edece5e06275bf0463aaf3")). pipe(fs.createWriteStream('./outputFile'));
注意
GridFS流式API无法加载部分块。当下载流需要从MongoDB中提取块时,它将整个块拉入内存。默认的255千字节块大小通常足够,但您可以将块大小减小以减少内存开销。
有关openDownloadStreamByName()
方法的更多信息,请参阅其API文档。
重命名文件
使用 rename()
方法更新您存储桶中 GridFS 文件的名称。您必须通过文件的 _id
字段来指定要重命名的文件,而不是其文件名。
注意
rename()
方法一次只能更新一个文件的名称。要重命名多个文件,从存储桶中检索与文件名匹配的文件列表,从您想要重命名的文件中提取 _id
字段,并将每个值分别调用 rename()
方法。
以下示例显示了如何通过引用文档的 _id
字段来更新 filename
字段为 "newFileName"。
bucket.rename(ObjectId("60edece5e06275bf0463aaf3"), "newFileName");
有关此方法的更多信息,请参阅 rename() API 文档。
删除文件
使用 delete()
方法从您的存储桶中删除文件。您必须通过文件的 _id
字段来指定文件,而不是其文件名。
注意
delete()
方法一次只能删除一个文件。要删除多个文件,从存储桶中检索文件,从您想要删除的文件中提取 _id
字段,并将每个值分别调用 delete()
方法。
以下示例显示了如何通过引用文件的 _id
字段来删除文件。
bucket.delete(ObjectId("60edece5e06275bf0463aaf3"));
有关此方法的更多信息,请参阅delete() API 文档。
删除 GridFS 桶
使用 drop()
方法删除桶的 files
和 chunks
集合,从而有效地删除桶。以下代码示例显示了如何删除 GridFS 桶
bucket.drop();
有关此方法的更多信息,请参阅drop() API 文档。