文档菜单
文档首页
/ / /
Rust 驱动
/

GridFS

本页内容

  • 概述
  • GridFS工作原理
  • 引用GridFS存储桶
  • 上传文件
  • 下载文件
  • 检索文件信息
  • 重命名文件
  • 删除文件
  • 删除GridFS存储桶
  • 其他信息
  • API 文档

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

如果您文件的尺寸超过16MB的BSON文档大小限制,请使用GridFS。GridFS还可以帮助您在不将整个文件加载到内存的情况下访问文件。有关GridFS是否适合您的用例的更详细信息,请参阅服务器手册中的GridFS页面。GridFS页面。

要了解更多关于GridFS的信息,请参阅本指南的以下部分

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

  • chunks,存储二进制文件块

  • files,存储文件元数据

当您创建一个新的GridFS存储桶时,Rust驱动程序执行以下操作

  • 创建以默认存储桶名称fs为前缀的chunksfiles集合,除非您指定不同的名称

  • 在每个集合上创建索引,以确保高效检索文件和相关元数据

您可以通过遵循本页的引用GridFS存储桶部分中的步骤来创建对GridFS存储桶的引用。但是,直到第一次写入操作之前,驱动程序不会创建新的GridFS存储桶及其索引。有关GridFS索引的更多信息,请参阅服务器手册中的GridFS索引页面。

当将文件存储在GridFS桶中时,Rust驱动程序会创建以下文档

  • files集合中创建一个文档,用于存储唯一的文件ID、文件名和其他文件元数据

  • chunks集合中创建一个或多个文档,用于存储文件内容,驱动程序将其拆分成更小的部分

以下图表描述了GridFS在上传到桶时如何拆分文件

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

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

在将文件存储到GridFS桶之前,创建一个桶引用或获取现有桶的引用。

以下示例在数据库实例上调用gridfs_bucket()方法,它创建对新或现有GridFS桶的引用

let bucket = my_db.gridfs_bucket(None);

您可以通过设置GridFsBucketOptions结构体的bucket_name字段来指定自定义桶名称。

注意

结构体实例化

Rust驱动程序为某些结构类型实现了Builder设计模式,包括GridFsBucketOptions。您可以使用builder()方法通过链接选项构建方法来构建每种类型的实例。

以下表格描述了您可以使用的方法来设置GridFsBucketOptions字段

方法
可能值
描述
bucket_name()
任何String
指定桶名称,默认设置为fs
chunk_size_bytes()
任何u32
指定用于将文件拆分成块的字块大小,默认为255 KB
write_concern()
WriteConcern::w(),
WriteConcern::w_timeout(),
WriteConcern::journal(),
WriteConcern::majority()
指定桶的写关注,默认设置为数据库的写关注
read_concern()
ReadConcern::local()ReadConcern::majority()ReadConcern::linearizable()ReadConcern::available()ReadConcern::snapshot()
指定桶的读关注,默认设置为数据库的读关注
selection_criteria()
SelectionCriteria::ReadPreference,
SelectionCriteria::Predicate
指定哪些服务器适用于桶操作,该操作设置为数据库的选择条件,默认为
默认条件

以下示例指定了GridFsBucketOptions实例中的选项,以配置自定义桶名称和写入操作的五秒超时限制

let wc = WriteConcern::builder().w_timeout(Duration::new(5, 0)).build();
let opts = GridFsBucketOptions::builder()
.bucket_name("my_bucket".to_string())
.write_concern(wc)
.build();
let bucket_with_opts = my_db.gridfs_bucket(opts);

您可以通过打开上传流并将文件写入流来将文件上传到GridFS桶。在您的桶实例上调用open_upload_stream()方法以打开流。此方法返回一个GridFsUploadStream实例,您可以将文件内容写入其中。要将文件内容上传到GridFsUploadStream,请调用write_all()方法并将您的文件字节作为参数传递。

提示

导入所需的模块

GridFsUploadStream结构实现了futures_io::AsyncWrite特性。要使用AsyncWrite写入方法,如write_all(),将AsyncWriteExt模块导入您的应用程序文件,并使用以下use声明

use futures_util::io::AsyncWriteExt;

以下示例使用上传流将名为"example.txt"的文件上传到GridFS桶

let bucket = my_db.gridfs_bucket(None);
let file_bytes = fs::read("example.txt").await?;
let mut upload_stream = bucket.open_upload_stream("example").await?;
upload_stream.write_all(&file_bytes[..]).await?;
println!("Document uploaded with ID: {}", upload_stream.id());
upload_stream.close().await?;

您可以通过打开下载流从GridFS桶中读取文件。在您的桶实例上调用open_download_stream()方法,指定所需文件的_id值作为参数。此方法返回一个GridFsDownloadStream实例,您可以通过它访问文件。要从GridFsDownloadStream读取文件,请调用read_to_end()方法并将向量作为参数传递。

提示

导入所需的模块

结构体GridFsDownloadStream实现了futures_io::AsyncRead特质。要使用AsyncRead的读取方法,如read_to_end(),请在您的应用程序文件中导入AsyncReadExt模块,使用以下use声明

use futures_util::io::AsyncReadExt;

以下示例使用下载流从GridFS存储桶中下载一个值为3289的文件

let bucket = my_db.gridfs_bucket(None);
let id = ObjectId::from_str("3289").expect("Could not convert to ObjectId");
let mut buf = Vec::new();
let mut download_stream = bucket.open_download_stream(Bson::ObjectId(id)).await?;
let result = download_stream.read_to_end(&mut buf).await?;
println!("{:?}", result);

注意

GridFS流式API不能加载部分块。当下载流需要从MongoDB中拉取一个块时,它会将整个块拉入内存。255 KB的默认块大小通常足够,但您可以减小块大小以减少内存开销。

您可以从GridFS存储桶的files集合中检索文件信息。每个文件都存储为FilesCollectionDocument类型的实例,该类型包括以下字段,代表文件信息

  • _id:文件ID

  • length:文件大小

  • chunk_size_bytes:文件块的大小

  • upload_date:文件的上传日期和时间

  • filename:文件名

  • metadata:存储用户指定元数据的文档

在GridFS存储桶实例上调用find()方法以从存储桶中检索文件。该方法返回一个游标实例,您可以通过该实例访问结果。

以下示例检索并打印GridFS存储桶中每个文件的大小

let bucket = my_db.gridfs_bucket(None);
let filter = doc! {};
let mut cursor = bucket.find(filter).await?;
while let Some(result) = cursor.try_next().await? {
println!("File length: {}\n", result.length);
};

提示

有关find()方法的更多信息,请参阅检索数据指南。有关从游标检索数据的更多信息,请参阅使用游标访问数据指南。

您可以通过在bucket实例上调用rename()方法来更新bucket中GridFS文件的名字。将目标文件的_id值和新文件名作为参数传递给rename()方法。

注意

rename()方法一次只能更新一个文件的名字。要重命名多个文件,从bucket中检索匹配文件名的文件列表,从您想要重命名的文件中提取_id字段,并将每个值单独调用rename()方法。

以下示例将包含_id值为3289的文件的filename字段更新为"new_file_name"

let bucket = my_db.gridfs_bucket(None);
let id = ObjectId::from_str("3289").expect("Could not convert to ObjectId");
let new_name = "new_file_name";
bucket.rename(Bson::ObjectId(id), new_name).await?;

您可以使用delete()方法从bucket中删除文件。要删除文件,请在bucket实例上调用delete()并传递文件的_id值作为参数。

注意

delete()方法一次只能删除一个文件。要删除多个文件,从bucket中检索文件,从您想要删除的文件中提取_id字段,并将每个_id值单独调用delete()方法。

以下示例删除了_id字段值为3289的文件。

let bucket = my_db.gridfs_bucket(None);
let id = ObjectId::from_str("3289").expect("Could not convert to ObjectId");
bucket.delete(Bson::ObjectId(id)).await?;

您可以使用 drop() 方法来删除存储桶,这将删除存储桶的 fileschunks 集合。要删除存储桶,请在其实例上调用 drop()

以下示例演示了如何删除 GridFS 存储桶

let bucket = my_db.gridfs_bucket(None);
bucket.drop().await?;

要了解更多关于本指南中提到的任何方法或类型的信息,请参阅以下 API 文档

返回

地理空间搜索