Join us Sept 17 at .local NYC! Use code WEB50 to save 50% on tickets. Learn more >
MongoDB Event
Docs 菜单
Docs 主页
/ / /
C#/ .NET驱动程序
/

存储大文件

在本指南中,您可以学习;了解如何使用GridFS在MongoDB中存储和检索大文件。GridFS存储系统在存储文件时将文件拆分为数据段,并在检索文件时重新组合这些文件。 GridFS驱动程序的实施是一个抽象,用于管理文件存储的操作和组织。

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

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

  • chunks:存储二进制文件段

  • files:存储文件元数据

当您首次向 GridFS 存储桶写入数据时,驾驶员会创建GridFS存储桶(如果尚不存在)。 存储桶包含 chunksfiles 集合,前缀为默认桶名称 fs,除非您指定其他名称。 为了确保有效检索文件和相关元数据,驾驶员会在每个集合上创建一个索引。 在对GridFS存储桶执行写入操作之前,驾驶员会确保这些索引存在。

有关GridFS索引的更多信息,请参阅MongoDB Server手册中的GridFS索引。MongoDB Server

使用GridFS存储文件时,驾驶员会将文件分割成较小的数据段,每个数据段由 chunks集合中的单独文档表示。 它还在 files集合中创建一个文档,其中包含文件ID、文件名和其他文件元数据。

下图展示了GridFS在上传到存储桶时如何分割文件:

显示 GridFS 如何将文件上传到存储桶的图表

在检索文件时,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

用于存储桶操作的读关注(read concern)。 默认值为数据库的读关注(read concern)。

数据类型ReadConcern

ReadPreference

用于存储桶操作的读取偏好(read preference)。 默认值为数据库的读取偏好(read preference)。

数据类型ReadPreference

WriteConcern

用于存储桶操作的写关注(write concern)。 默认值为数据库的写关注(write concern)。

数据类型写关注

以下示例通过将 GridFSBucketOptions 类的实例传递给 GridFSBucket() 构造函数来创建名为 "myCustomBucket" 的存储桶:

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

您可以使用以下方法将文件上传到GridFS存储桶:

  • OpenUploadStream()OpenUploadStreamAsync():打开新的上传流,您可以向其中写入文件内容

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

以下部分介绍如何使用这些方法。

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

Parameter
说明

filename

要上传的文件的名称。

数据类型string

options

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

数据类型:GridFSUploadOptions

cancellationToken

可选。可用于取消操作的令牌。

数据类型:CancellationToken

此代码示例演示如何通过执行以下步骤来打开上传流:

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

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

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

选择 SynchronousAsynchronous标签页以查看相应的代码:

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?

Metadata

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

  • 文件的 _id

  • 文件的名称

  • 文件的长度和大小

  • 上传日期和时间

  • 可以在其中存储其他信息的 metadata文档

默认值为 null

数据类型:BsonDocument

以下示例执行与前一示例相同的步骤,但也使用 ChunkSizeBytes 选项指定每个数据块的大小。 选择 SynchronousAsynchronous标签页以查看相应的代码。

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文件。 这些方法接受以下参数:

Parameter
说明

filename

要上传的文件的名称。

数据类型string

source

要从中读取文件内容的流。

数据类型:流

options

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

数据类型:GridFSUploadOptions

cancellationToken

可选。可用于取消操作的令牌。

数据类型:CancellationToken

此代码示例演示如何通过执行以下步骤来打开上传流:

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

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

选择 SynchronousAsynchronous 标签页,查看相应的代码。

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() 方法创建下载流。 这些方法接受以下参数:

Parameter
说明

id

要下载的文件的 _id 值。

数据类型:BsonValue

options

可选。指定下载流配置的 GridFSDownloadOptions 类的实例。 默认值为 null

数据类型:GridFSDownloadOptions

cancellationToken

可选。可用于取消操作的令牌。

数据类型:CancellationToken

以下代码示例演示了如何通过执行以下步骤来打开下载流:

  • 检索名为 "new_file" 的GridFS文件的 _id

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

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

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

选择 SynchronousAsynchronous 标签页,查看相应的代码。

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

指示流是否支持查找、查询和更改流中当前位置的能力。默认值为 false

数据类型bool?

以下示例执行与前面的示例相同的步骤,但还将 Seekable 选项设置为 true 以指定该流是可查找的。

选择 SynchronousAsynchronous 标签页,查看相应的代码。

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文件的内容下载到现有流。 这些方法接受以下参数:

Parameter
说明

id

要下载的文件的 _id 值。

数据类型:BsonValue

destination

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

数据类型:流

options

可选。指定下载流配置的 GridFSDownloadOptions 类的实例。 默认值为 null

数据类型:GridFSDownloadOptions

cancellationToken

可选。可用于取消操作的令牌。

数据类型:CancellationToken

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

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

  • 检索名为 "new_file" 的GridFS文件的 _id

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

选择 SynchronousAsynchronous 标签页,查看相应的代码。

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() 方法。 这些方法接受以下参数:

Parameter
说明

filter

查询过滤,用于指定 files集合中要匹配的条目。

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

source

要从中读取文件内容的流。

数据类型:流

options

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

数据类型:GridFSFindOptions

cancellationToken

可选。可用于取消操作的令牌。

数据类型:CancellationToken

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

选择 SynchronousAsynchronous 标签页,查看相应的代码。

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 类包含以下属性:

属性
说明

Sort

结果的排序顺序。 如果未指定排序顺序,该方法将按插入顺序返回结果。

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

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

DeleteDeleteAsync() 方法接受以下参数:

Parameter
说明

id

要删除的文件的_id

数据类型:BsonValue

cancellationToken

可选。可用于取消操作的令牌。

数据类型:CancellationToken

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

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

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

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

选择 SynchronousAsynchronous 标签页,查看相应的代码。

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文档:

后退

事务

在此页面上