文档菜单
文档首页
/ / /
Node.js 驱动程序
/

GridFS

在本页面上

  • 概述
  • 如何GridFS工作
  • 创建GridFS存储桶
  • 上传文件
  • 检索文件信息
  • 下载文件
  • 重命名文件
  • 删除文件
  • 删除GridFS存储桶
  • 其他资源

在本指南中,您可以了解如何使用GridFS在MongoDB中存储和检索大文件。GridFS是一个规范,它描述了如何在存储期间将文件分割成块,并在检索期间重新组合它们。GridFS的驱动程序实现管理文件存储的操作和组织。

如果您的文件大小超过了16兆字节的BSON文档大小限制,请使用GridFS。有关GridFS是否适合您的用例的更多详细信息,请参阅GridFS服务器手册页.

导航以下部分,以了解更多关于GridFS操作和实现的信息

GridFS 将文件组织在 存储桶 中,这是一个包含文件块和描述性信息的 MongoDB 集合组。存储桶包含以下集合,名称遵循 GridFS 规范中定义的约定

  • 以下chunks 集合存储二进制文件块。

  • files 集合存储文件元数据。

创建新的 GridFS 存储桶时,驱动程序会创建 chunksfiles 集合,默认使用 fs 作为前缀,除非指定了不同的名称。驱动程序还会在每个集合上创建索引,以确保文件和相关元数据的有效检索。如果存储桶不存在,驱动程序仅在第一次写入操作时创建 GridFS 存储桶。如果索引不存在且存储桶为空,驱动程序才会创建索引。有关 GridFS 索引的更多信息,请参阅服务器手册页面 GridFS 索引。

使用 GridFS 存储文件时,驱动程序会将文件拆分为更小的部分,每个部分由 chunks 集合中的一个单独文档表示。它还会在 files 集合中创建一个文档,其中包含唯一的文件 ID、文件名和其他文件元数据。您可以从内存或从流中上传文件。以下图解描述了 GridFS 在上传到存储桶时如何分割文件

A diagram that shows how GridFS uploads a file to a bucket

检索文件时,GridFS 从指定存储桶的 files 集合中获取元数据,并使用该信息从 chunks 集合的文档中重建文件。您可以将文件读入内存或将输出输出到流中。

创建一个存储桶或获取现有存储桶的引用以开始从 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() 结合使用。

有关本节中提到的类和方法的更多信息,请参阅以下资源

  • find() API 文档

  • FindCursor API 文档

  • 游标基础页面

  • 读取操作页面

您可以使用来自GridFSBucketopenDownloadStreamByName()方法从您的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 文档。

使用 drop() 方法删除桶的 fileschunks 集合,从而有效地删除桶。以下代码示例显示了如何删除 GridFS 桶

bucket.drop();

有关此方法的更多信息,请参阅drop() API 文档。

返回

连接池