文档菜单
文档首页
/ / /
PyMongo
/

存储大文件

本页内容

  • 概述
  • GridFS是如何工作的
  • 创建GridFS存储桶
  • 上传文件
  • 检索文件信息
  • 下载文件
  • 重命名文件
  • 删除文件
  • API文档

本指南介绍了如何使用GridFS在MongoDB中存储和检索大文件。GridFS是PyMongo实现的一个规范,它描述了在存储时如何将文件分割成块,以及在检索时如何重新组装这些块。GridFS的驱动实现是一个抽象层,用于管理文件存储的操作和组织。

当你的文件大小超过16MB的BSON文档大小限制时,你应该使用GridFS。有关GridFS是否适合你的用例的更多信息,请参阅GridFS在MongoDB服务器手册中。

以下部分描述了GridFS的操作及其执行方式。

GridFS将文件组织在名为bucket的集合中,这是一个包含文件块及其描述信息的MongoDB集合组。bucket包含以下集合,使用GridFS规范中定义的约定命名

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

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

当你创建一个新的GridFS bucket时,驱动程序会创建上述集合,默认以fs为前缀,除非你指定了不同的名称。驱动程序还会为每个集合创建索引,以确保高效检索文件和相关元数据。驱动程序仅在首次执行写入操作时创建GridFS bucket,如果它不存在。驱动程序仅在索引不存在且bucket为空时创建索引。有关GridFS索引的更多信息,请参阅MongoDB服务器手册中的GridFS Indexes

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

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

在检索文件时,GridFS从指定bucket中的files集合中检索元数据,并使用这些信息从chunks集合中的文档重建文件。你可以将文件读入内存或将输出输出到流。

要存储或检索GridFS中的文件,请通过调用GridFSBucket()构造函数并传入一个Database实例来创建一个GridFS存储桶。您可以使用GridFSBucket实例在存储桶中的文件上调用读写操作。

client = MongoClient("<connection string>")
db = client["db"]
bucket = gridfs.GridFSBucket(db)

要创建或引用一个名为默认名称fs以外的自定义名称的存储桶,请将您的存储桶名称作为GridFSBucket()构造函数的第二个参数传递,如下所示

custom_bucket = gridfs.GridFSBucket(db, bucket_name="myCustomBucket")

使用GridFSBucket类中的open_upload_stream()方法为给定的文件名创建一个上传流。该方法允许您指定配置信息,例如文件块大小和其他作为元数据存储的字段/值对。将这些选项作为open_upload_stream()的参数设置,如下面的代码示例所示

with bucket.open_upload_stream(
"my_file", chunk_size_bytes=1048576, metadata={"contentType": "text/plain"}
) as grid_in:
grid_in.write("data to store")

在本节中,您可以学习如何检索存储在GridFS桶的files集合中的文件元数据。元数据包含关于其引用的文件的信息,包括

  • 文件_id

  • 文件名

  • 文件长度/大小

  • 上传日期和时间

  • 一个metadata文档,您可以在其中存储任何其他信息

要从一个GridFS桶中检索文件,请调用GridFSBucket实例上的find()方法。此方法返回一个Cursor实例,您可以从该实例访问结果。有关PyMongo中Cursor对象的更多信息,请参阅从游标访问数据.

以下代码示例展示了如何从GridFS桶中的所有文件中检索和打印文件元数据。它使用for...in语法遍历Cursor可迭代对象并显示结果

for file_doc in bucket.find({}):
print(file_doc)

find()方法接受各种查询规范。您可以使用其参数指定排序顺序、返回的最大文档数以及在返回之前跳过的文档数。有关MongoDB查询的更多信息,请参阅检索数据。

您可以通过使用来自GridFSBucketopen_download_stream_by_name()方法来创建下载流,从而从MongoDB数据库中下载文件。

以下示例展示了如何通过文件名"my_file"下载文件并读取其内容

file = bucket.open_download_stream_by_name("my_file")
contents = file.read()

注意

如果有多个文档具有相同的filename值,GridFS将流式传输具有给定名称的最新文件(根据uploadDate字段确定)。

或者,您可以使用接受文件_id字段作为参数的open_download_stream()方法

file = bucket.open_download_stream(ObjectId("66b3c86e672a17b6c8a4a4a9"))
contents = file.read()

注意

GridFS流式API无法加载部分块。当下载流需要从MongoDB中拉取一个块时,它会将整个块加载到内存中。默认的255千字节块大小通常足够使用,但您可以通过减小块大小来减少内存开销。

使用rename()方法更新您的桶中GridFS文件的名称。您必须通过其_id字段来指定要重命名的文件,而不是通过其文件名。

以下示例展示了如何通过引用文档的_id字段来更新filename字段为"new_file_name"

bucket.rename(ObjectId("66b3c86e672a17b6c8a4a4a9"), "new_file_name")

注意

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

使用delete()方法从您的桶中删除文件的集合文档和相关块。这将有效地删除文件。您必须通过其_id字段来指定文件,而不是通过其文件名。

以下示例展示了如何通过引用其_id字段来删除文件。

bucket.delete(ObjectId("66b3c86e672a17b6c8a4a4a9"))

注意

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

要了解更多关于使用 PyMongo 存储和检索大文件的信息,请参阅以下 API 文档

返回

批量写入操作