文档菜单
文档首页
/ / /
C#/.NET
/

存储大文件

在本页面上

  • 概述
  • GridFS 的工作原理
  • 创建 GridFS 存储桶
  • 自定义存储桶
  • 上传文件
  • 写入上传流
  • 上传现有流
  • 下载文件
  • 从下载流中读取
  • 下载到现有流
  • 查找文件
  • 删除文件
  • API 文档

在本指南中,您将学习如何通过使用 GridFS 在 MongoDB 中存储和检索大文件。GridFS 存储系统在存储文件时会将文件分割成块,并在检索时重新组装这些文件。GridFS 的驱动程序实现是一个抽象层,用于管理文件存储的操作和组织。

如果您的任何文件大小超过 16 MB 的 BSON 文档大小限制,请使用 GridFS。有关 GridFS 是否适合您用例的更详细信息,请参阅GridFS MongoDB 服务器手册。

GridFS 将文件组织在 存储桶 中,存储桶是一组包含文件块及其描述信息的 MongoDB 集合。存储桶包含以下集合

  • chunks:存储二进制文件块

  • files:存储文件元数据

当您首次向驱动器写入数据时,如果该桶不存在,驱动器会创建GridFS桶。该桶包含以默认桶名fs为前缀的chunksfiles集合,除非您指定了不同的名称。为了确保高效检索文件和相关元数据,驱动器会在每个集合上创建一个索引。在GridFS桶上执行读取和写入操作之前,驱动器确保这些索引存在。

有关GridFS索引的更多信息,请参阅MongoDB服务器手册中的GridFS Indexes

当使用GridFS存储文件时,驱动器会将文件拆分为更小的块,每个块由chunks集合中的一个单独文档表示。它还在files集合中创建一个文档,其中包含文件ID、文件名和其他文件元数据。

以下图表显示了GridFS在将文件上传到桶时如何拆分文件

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

在检索文件时,GridFS从指定桶中的files集合中检索元数据,并使用这些信息从chunks集合中的文档重新构建文件。

要开始使用GridFS存储或检索文件,请创建一个新的GridFSBucket实例,并传入一个代表您的数据库的IMongoDatabase对象。此方法访问现有桶或创建一个新桶(如果不存在)。

以下示例为db数据库创建一个新的GridFSBucket实例

var client = new MongoClient("<connection string>");
var database = client.GetDatabase("db");
// Creates a GridFS bucket or references an existing one
var bucket = new GridFSBucket(database);

您可以通过将GridFSBucketOptions类的实例传递给GridFSBucket()构造函数来自定义GridFS存储桶配置。以下表格描述了GridFSBucketOptions类中的属性。

字段
描述

BucketName

用于文件和块集合的前缀的存储桶名称。默认值为"fs"

数据类型: string

ChunkSizeBytes

GridFS将文件分割成的块大小。默认值为255 KB。

数据类型: integer

ReadConcern

用于存储桶操作的读取关注点。默认值是数据库的读取关注点。

数据类型: ReadConcern

ReadPreference

用于存储桶操作的读取偏好。默认值是数据库的读取偏好。

数据类型: ReadPreference

WriteConcern

用于存储桶操作的写入关注点。默认值是数据库的写入关注点。

数据类型WriteConcern

以下示例通过将GridFSBucketOptions类的实例传递给GridFSBucket()构造函数,创建了一个名为"myCustomBucket"的bucket。

var options = new GridFSBucketOptions { BucketName = "myCustomBucket" };
var customBucket = new GridFSBucket(database, options);

您可以使用以下方法将文件上传到GridFS bucket。

  • OpenUploadStream()OpenUploadStreamAsync():打开一个新上传流,您可以写入文件内容。

  • UploadFromStream()UploadFromStreamAsync():将现有流的内容上传到GridFS文件。

以下部分描述了如何使用这些方法。

使用 OpenUploadStream()OpenUploadStreamAsync() 方法创建指定文件名的上传流。这些方法接受以下参数:

参数
描述

filename

要上传的文件名。

数据类型: string

options

可选。 一个 GridFSUploadOptions 类的实例,该实例指定上传流的配置。默认值为 null

数据类型: GridFSUploadOptions

cancellationToken

可选。 一个可以用来取消操作的令牌。

数据类型: CancellationToken

以下代码示例演示了如何通过以下步骤打开上传流:

  • 调用 OpenUploadStream() 方法打开名为 "my_file" 的可写 GridFS 流

  • 调用 Write() 方法将数据写入 my_file

  • 调用 Close() 方法关闭指向 my_file 的流

选择同步异步 选项卡以查看相应的代码

using (var uploader = bucket.OpenUploadStream("my_file"))
{
// ASCII for "HelloWorld"
byte[] bytes = { 72, 101, 108, 108, 111, 87, 111, 114, 108, 100 };
uploader.Write(bytes, 0, bytes.Length);
uploader.Close();
}
using (var uploader = await bucket.OpenUploadStreamAsync("my_file", options))
{
// ASCII for "HelloWorld"
byte[] bytes = { 72, 101, 108, 108, 111, 87, 111, 114, 108, 100 };
await uploader.WriteAsync(bytes, 0, bytes.Length);
await uploader.CloseAsync();
}

要自定义上传流配置,将 GridFSUploadOptions 类的实例传递给 OpenUploadStream()OpenUploadStreamAsync() 方法。GridFSUploadOptions 类包含以下属性:

属性
描述

BatchSize

每个批次中上传的块数。默认值为 16 MB 除以 ChunkSizeBytes 属性的值。

数据类型: int?

ChunkSizeBytes

除了最后一个块的大小较小外,每个块的大小。默认值为255 KB。

数据类型: int?

元数据

与文件一起存储的元数据,包括以下元素

  • 文件的 _id

  • 文件的名称

  • 文件长度和大小

  • 上传日期和时间

  • 一个您可以存储其他信息的 元数据 文档

默认值为 null

数据类型: BsonDocument

以下示例执行了前面示例中的相同步骤,但还使用了 ChunkSizeBytes 选项来指定每个块的大小。选择 同步异步 选项卡以查看相应的代码。

var options = new GridFSUploadOptions
{
ChunkSizeBytes = 1048576 // 1 MB
};
using (var uploader = bucket.OpenUploadStream("my_file", options))
{
// ASCII for "HelloWorld"
byte[] bytes = { 72, 101, 108, 108, 111, 87, 111, 114, 108, 100 };
uploader.Write(bytes, 0, bytes.Length);
uploader.Close();
}
var options = new GridFSUploadOptions
{
ChunkSizeBytes = 1048576 // 1 MB
};
using (var uploader = await bucket.OpenUploadStreamAsync("my_file", options))
{
// ASCII for "HelloWorld"
byte[] bytes = { 72, 101, 108, 108, 111, 87, 111, 114, 108, 100 };
await uploader.WriteAsync(bytes, 0, bytes.Length);
await uploader.CloseAsync();
}

使用 UploadFromStream()UploadFromStreamAsync() 方法将流的内容上传到新的 GridFS 文件。这些方法接受以下参数

参数
描述

filename

要上传的文件名。

数据类型: string

source

读取文件内容的流。

数据类型: Stream

options

可选。 一个 GridFSUploadOptions 类的实例,该实例指定上传流的配置。默认值为 null

数据类型: GridFSUploadOptions

cancellationToken

可选。 一个可以用来取消操作的令牌。

数据类型: CancellationToken

以下代码示例演示了如何通过以下步骤打开上传流:

  • 以二进制读取模式打开位于 /path/to/input_file 的文件作为流

  • 调用 UploadFromStream() 方法,将流的内容写入名为 "new_file" 的 GridFS 文件

选择 同步异步 选项卡,查看相应的代码。

using (var fileStream = new FileStream("/path/to/input_file", FileMode.Open, FileAccess.Read))
{
bucket.UploadFromStream("new_file", fileStream);
}
using (var fileStream = new FileStream("/path/to/input_file", FileMode.Open, FileAccess.Read))
{
await bucket.UploadFromStreamAsync("new_file", fileStream);
}

您可以使用以下方法从 GridFS 存储桶下载文件

  • OpenDownloadStream()OpenDownloadStreamAsync():打开一个新的下载流,您可以从该流中读取文件内容

  • DownloadToStream()DownloadToStreamAsync():将 GridFS 文件的内容写入现有的流

以下各节更详细地描述了这些方法。

使用 OpenDownloadStream()OpenDownloadStreamAsync() 方法创建下载流。这些方法接受以下参数

参数
描述

id

要下载的文件的 _id 值。

数据类型: BsonValue

options

可选。 一个 GridFSDownloadOptions 类的实例,用于指定下载流的配置。默认值是 null

数据类型: GridFSDownloadOptions

cancellationToken

可选。 一个可以用来取消操作的令牌。

数据类型: CancellationToken

以下代码示例展示了如何通过以下步骤打开下载流:

  • 获取名为 "new_file" 的 GridFS 文件的 _id

  • 调用 OpenDownloadStream() 方法并将 _id 值传递以将文件作为可读 GridFS 流打开

  • 创建一个 buffer 向量以存储文件内容

  • 调用 Read() 方法从 downloader 流读取文件内容到向量

选择 同步异步 选项卡,查看相应的代码。

var filter = Builders<GridFSFileInfo>.Filter.Eq(x => x.Filename, "new_file");
var doc = bucket.Find(filter).FirstOrDefault();
if (doc != null)
{
using (var downloader = bucket.OpenDownloadStream(doc.Id))
{
var buffer = new byte[downloader.Length];
downloader.Read(buffer, 0, buffer.Length);
// Process the buffer as needed
}
}
var filter = Builders<GridFSFileInfo>.Filter.Eq(x => x.Filename, "new_file");
var cursor = await bucket.FindAsync(filter);
var fileInfoList = await cursor.ToListAsync();
var doc = fileInfoList.FirstOrDefault();
if (doc != null)
{
using (var downloader = await bucket.OpenDownloadStreamAsync(doc.Id))
{
var buffer = new byte[downloader.Length];
await downloader.ReadAsync(buffer, 0, buffer.Length);
// Process the buffer as needed
}
}

要自定义下载流配置,将 GridFSDownloadOptions 类的实例传递给 OpenDownloadStream() 方法。GridFSDownloadOptions 类包含以下属性:

属性
描述

Seekable

指示流是否支持 seeking(定位),即在流中查询和更改当前位置的能力。默认值是 false

数据类型: bool?

以下示例与上一个示例执行相同的步骤,但还设置了Seekable选项为true以指定流是可寻址的。

选择 同步异步 选项卡,查看相应的代码。

var filter = Builders<GridFSFileInfo>.Filter.Eq(x => x.Filename, "new_file");
var doc = bucket.Find(filter).FirstOrDefault();
if (doc != null)
{
var options = new GridFSDownloadOptions
{
Seekable = true
};
using (var downloader = bucket.OpenDownloadStream(id, options))
{
var buffer = new byte[downloader.Length];
downloader.Read(buffer, 0, buffer.Length);
// Process the buffer as needed
}
}
var filter = Builders<GridFSFileInfo>.Filter.Eq(x => x.Filename, "new_file");
var cursor = await bucket.FindAsync(filter);
var fileInfoList = await cursor.ToListAsync();
var doc = fileInfoList.FirstOrDefault();
if (doc != null)
{
var options = new GridFSDownloadOptions
{
Seekable = true
};
using (var downloader = await bucket.OpenDownloadStreamAsync(doc.Id, options))
{
var buffer = new byte[downloader.Length];
await downloader.ReadAsync(buffer, 0, buffer.Length);
// Process the buffer as needed
}
}

使用DownloadToStream()DownloadToStreamAsync()方法将GridFS文件的内容下载到现有流。这些方法接受以下参数

参数
描述

id

要下载的文件的 _id 值。

数据类型: BsonValue

目标

该流是.NET/C#驱动程序将GridFS文件下载到其中的流。此属性的值必须是实现Stream类的对象。

数据类型: Stream

options

可选。 一个 GridFSDownloadOptions 类的实例,用于指定下载流的配置。默认值是 null

数据类型: GridFSDownloadOptions

cancellationToken

可选。 一个可以用来取消操作的令牌。

数据类型: CancellationToken

以下代码示例演示了如何通过执行以下操作将内容下载到现有流

  • 以二进制写入模式打开位于/path/to/output_file的文件作为流

  • 获取名为 "new_file" 的 GridFS 文件的 _id

  • 调用DownloadToStream()方法,并将_id值传递以将"new_file"的内容下载到流中

选择 同步异步 选项卡,查看相应的代码。

var filter = Builders<GridFSFileInfo>.Filter.Eq(x => x.Filename, "new_file");
var doc = bucket.Find(filter).FirstOrDefault();
if (doc != null)
{
using (var outputFile = new FileStream("/path/to/output_file", FileMode.Create, FileAccess.Write))
{
bucket.DownloadToStream(doc.Id, outputFile);
}
}
var filter = Builders<GridFSFileInfo>.Filter.Eq(x => x.Filename, "new_file");
var cursor = await bucket.FindAsync(filter);
var fileInfoList = await cursor.ToListAsync();
var doc = fileInfoList.FirstOrDefault();
if (doc != null)
{
using (var outputFile = new FileStream("/path/to/output_file", FileMode.Create, FileAccess.Write))
{
await bucket.DownloadToStreamAsync(doc.Id, outputFile);
}
}

要在GridFS存储桶中查找文件,请在您的GridFSBucket实例上调用Find()FindAsync()方法。这些方法接受以下参数

参数
描述

filter

一个查询过滤器,用于指定在files集合中匹配的条目。

数据类型FilterDefinition<GridFSFileInfo>。有关更多信息,请参阅Find()方法的相关API文档。

source

读取文件内容的流。

数据类型: Stream

options

可选。一个GridFSFindOptions类的实例,用于指定查找操作的配置。默认值为null

数据类型GridFSFindOptions

cancellationToken

可选。 一个可以用来取消操作的令牌。

数据类型: CancellationToken

以下代码示例展示了如何从GridFS存储桶中的文件检索并打印文件元数据。Find()方法返回一个IAsyncCursor<GridFSFileInfo>实例,您可以通过该实例访问结果。它使用一个foreach循环遍历返回的游标,并显示上传文件示例中上传的文件的详细内容。

选择 同步异步 选项卡,查看相应的代码。

var filter = Builders<GridFSFileInfo>.Filter.Empty;
var files = bucket.Find(filter);
foreach (var file in files.ToEnumerable())
{
Console.WriteLine(file.ToJson());
}
{ "_id" : { "$oid" : "..." }, "length" : 13, "chunkSize" : 261120, "uploadDate" :
{ "$date" : ... }, "filename" : "new_file" }
{ "_id" : { "$oid" : "..." }, "length" : 50, "chunkSize" : 1048576, "uploadDate" :
{ "$date" : ... }, "filename" : "my_file" }
var filter = Builders<GridFSFileInfo>.Filter.Empty;
var files = await bucket.FindAsync(filter);
await files.ForEachAsync(file => Console.Out.WriteLineAsync(file.ToJson()))
{ "_id" : { "$oid" : "..." }, "length" : 13, "chunkSize" : 261120, "uploadDate" :
{ "$date" : ... }, "filename" : "new_file" }
{ "_id" : { "$oid" : "..." }, "length" : 50, "chunkSize" : 1048576, "uploadDate" :
{ "$date" : ... }, "filename" : "my_file" }

要自定义查找操作,将GridFSFindOptions类的实例传递给Find()FindAsync()方法。GridFSFindOptions类包含以下属性

属性
描述

排序

结果的排序顺序。如果您没有指定排序顺序,该方法将按照它们插入的顺序返回结果。

数据类型: SortDefinition<GridFSFileInfo>。有关更多信息,请参阅排序属性的API文档。

要从GridFS存储桶中删除文件,请在您的GridFSBucket实例上调用Delete()DeleteAsync()方法。此方法会从您的存储桶中删除文件的元数据集合及其相关的数据块。

DeleteDeleteAsync()方法接受以下参数

参数
描述

id

要删除的文件的 _id

数据类型: BsonValue

cancellationToken

可选。 一个可以用来取消操作的令牌。

数据类型: CancellationToken

以下代码示例展示了如何删除名为 "my_file" 的文件,通过传递其 _id 值给 delete_file()

  • 使用 Builders 类创建一个匹配名为 "my_file" 的文件的过滤器

  • 使用 Find() 方法查找名为 "my_file" 的文件

  • 将文件的 _id 值传递给 Delete() 方法以删除文件

选择 同步异步 选项卡,查看相应的代码。

var filter = Builders<GridFSFileInfo>.Filter.Eq(x => x.Filename, "new_file");
var doc = bucket.Find(filter).FirstOrDefault();
if (doc != null)
{
bucket.Delete(doc.Id);
}
var filter = Builders<GridFSFileInfo>.Filter.Eq(x => x.Filename, "new_file");
var cursor = await bucket.FindAsync(filter);
var fileInfoList = await cursor.ToListAsync();
var doc = fileInfoList.FirstOrDefault();
if (doc != null)
{
await bucket.DeleteAsync(doc.Id);
}

注意

文件修订版

Delete()DeleteAsync() 方法一次只能删除一个文件。如果您想删除每个文件修订版,或者具有相同文件名但上传时间不同的文件,请收集每个修订版的 _id 值。然后,将每个 _id 值单独调用 Delete()DeleteAsync() 方法。

要了解更多关于此页面上使用的类的信息,请参阅以下 API 文档

要了解更多关于此页面上使用的 GridFSBucket 类的方法,请参阅以下 API 文档

返回

地理空间搜索