Docs 菜单
Docs 主页
/ / /
C 驱动程序
/

存储大文件

在此页面上

  • Overview
  • GridFS 的工作原理
  • 创建 GridFS 存储桶
  • 自定义存储桶
  • 上传文件
  • 写入上传流
  • 上传现有流
  • 检索文件信息
  • 例子
  • 下载文件
  • 从下载流中读取
  • 下载到现有流
  • 删除文件
  • API 文档

在本指南中,您可以学习;了解如何使用GridFS在MongoDB中存储和检索大文件。 GridFS是由C驾驶员实现的规范,描述了如何在存储文件时将文件分割为数据段,并在检索文件时重新组合文件。 GridFS驱动程序的实施是一个抽象,用于管理文件存储的操作和组织。

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

GridFS 在存储桶中组织文件,存储桶是一组包含文件数据段及其描述信息的MongoDB 集合。存储桶包含以下集合,使用 GridFS 规范中定义的约定命名:

  • chunks 集合存储二进制文件数据段。

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

当您执行第一次写入操作时,驾驶员会创建GridFS存储桶(如果不存在)。存储桶包含以默认存储桶名称 fs 为前缀的前面的集合,除非您指定了其他名称。为了确保有效检索文件和相关元数据,驾驶员还会在每个集合上创建索引(如果它们不存在)以及存储桶为空。

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

使用GridFS存储文件时,驾驶员会将文件分割成较小的数据段,每个数据段由 chunks集合中的单独文档表示。它还在 files集合中创建一个文档,其中包含文件ID、文件名和其他文件元数据。您可以通过将流C驾驶员以使用或创建新流并直接写入来上传文件。

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

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

当您从GridFS检索文件时,它会从指定存储桶中的 files集合中获取元数据,并使用该信息根据 chunks集合中的文档重建文件。您可以通过将文件内容写入现有流或创建指向该文件的新流来读取该文件。

要使用GridFS,请先调用 mongoc_gridfs_bucket_new() 函数。此函数创建新的 mongoc_gridfs_bucket_t 结构或访问现有的 mongoc_gridfs_bucket_t 并接受以下参数:

  • Database :指定要在其中创建存储桶的数据库

  • 选项文档:指定用于自定义存储桶的选项,或NULL

  • 读取偏好 :指定用于读取操作的读取偏好(read preference),或NULL 以继承数据库的读取偏好(read preference)

  • 错误位置:指定错误值的位置,或NULL

以下示例调用 mongoc_gridfs_bucket_new() 函数并将 db数据库作为参数传递:

mongoc_database_t *db = mongoc_client_get_database (client, "db");
bson_error_t error;
if (!mongoc_gridfs_bucket_new (db, NULL, NULL, &error)) {
fprintf (stderr, "Failed to create bucket: %s\n", error.message);
}

您可以通过将指定选项值的BSON文档传递给 mongoc_gridfs_bucket_new() 函数来自定义GridFS存储桶配置。下表描述了您可以在文档中设立的选项:

选项
说明
bucketName
Specifies the bucket name to use as a prefix for the files and chunks collections. The default value is "fs".
Type: string
chunkSizeBytes
Specifies the chunk size that GridFS splits files into. The default value is 255 kB.
Type: int32
readConcern
Specifies the read concern to use for bucket operations. The default value is the database's read concern.
Type: mongoc_read_concern_t
writeConcern
Specifies the write concern to use for bucket operations. The default value is the database's write concern.
Type: mongoc_write_concern_t

以下示例通过将选项文档传递给设置 bucketName 选项的 mongoc_gridfs_bucket_new() 来创建名为 "myCustomBucket" 的存储桶:

mongoc_database_t *db = mongoc_client_get_database (client, "db");
bson_t opts = BSON_INITIALIZER;
BSON_APPEND_UTF8 (&opts, "bucketName", "myCustomBucket");
bson_error_t error;
if (!mongoc_gridfs_bucket_new (db, &opts, NULL, &error)) {
fprintf (stderr, "Failed to create bucket: %s\n", error.message);
}

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

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

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

使用 mongoc_gridfs_bucket_open_upload_stream() 函数为给定文件名创建上传流。 mongoc_gridfs_bucket_open_upload_stream() 函数允许您在选项文档中指定配置信息,您可以将其作为参数传递。

此示例使用上传流来执行以下操作:

  • 为名为以下内容的新GridFS文件打开可写流: "my_file"

  • 调用 mongoc_stream_write() 函数以写入"my_file",流指向

  • 调用 mongoc_stream_close()mongoc_stream_destroy() 函数以关闭并销毁指向 "my_file" 的流

bson_error_t error;
mongoc_stream_t *upload_stream = mongoc_gridfs_bucket_open_upload_stream (bucket, "my_file", NULL, NULL, &error);
if (upload_stream == NULL) {
fprintf (stderr, "Failed to create upload stream: %s\n", error.message);
} else {
const char *data = "Data to store";
mongoc_stream_write (upload_stream, data, strlen(data), -1);
}
mongoc_stream_close (upload_stream);
mongoc_stream_destroy (upload_stream);

使用 mongoc_gridfs_bucket_upload_from_stream() 函数将流的内容上传到新的GridFS文件。 mongoc_gridfs_bucket_upload_from_stream() 函数允许您在选项文档中指定配置信息,您可以将其作为参数传递。

此示例将执行以下动作:

  • 调用 mongoc_stream_file_new_for_path() 函数以以只读 (O_RDONLY)模式将位于 /path/to/input_file 的文件作为流打开

  • 调用 mongoc_gridfs_bucket_upload_from_stream() 函数以将流的内容上传到名为 "new_file" 的GridFS文件

  • 调用 mongoc_stream_close()mongoc_stream_destroy() 函数以关闭并销毁流

mongoc_stream_t *file_stream = mongoc_stream_file_new_for_path ("/path/to/input_file", O_RDONLY, 0);
bson_error_t error;
if (!mongoc_gridfs_bucket_upload_from_stream (bucket, "new_file", file_stream, NULL, NULL, &error)) {
fprintf (stderr, "Failed to upload file: %s\n", error.message);
}
mongoc_stream_close (file_stream);
mongoc_stream_destroy (file_stream);

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

  • 文件的 _id

  • 文件的名称

  • 文件的长度/大小

  • 上传日期和时间

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

要从GridFS存储桶检索文件,请调用 mongoc_gridfs_bucket_find() 函数并将您的存储桶作为参数传递。该函数返回一个游标,您可以通过该游标访问权限结果。

提示

要学习;了解有关C驾驶员中游标的详情,请参阅 从游标访问数据指南。

以下代码示例向您展示如何从GridFS存储桶中的文件检索和打印文件元数据。 它使用while循环遍历返回的游标,并显示上传文件示例中上传的文件的内容:

mongoc_cursor_t *cursor = mongoc_gridfs_bucket_find(bucket, bson_new(), NULL);
const bson_t *file_doc;
while (mongoc_cursor_next(cursor, &file_doc)) {
char *json = bson_as_json(file_doc, NULL);
printf("%s\n", json);
bson_free(json);
}
mongoc_cursor_destroy (cursor);
{ "_id" : { "$oid" : "..." }, "length" : 13, "chunkSize" : 261120, "uploadDate" :
{ "$date" : ... }, "filename" : "my_file", "metadata" : { } }
{ "_id" : { "$oid" : "..." }, "length" : 13, "chunkSize" : 261120, "uploadDate" :
{ "$date" : ... }, "filename" : "new_file", "metadata" : { } }

mongoc_gridfs_bucket_find()函数接受各种查询规范。您可以使用其选项参数来指定排序顺序、要返回的最大文档数以及在返回之前要跳过的文档数。要查看可用选项列表,请参阅 mongoc_collection_find_with_opts() API文档。

您可以使用以下函数从GridFS存储桶下载文件:

  • mongoc_gridfs_bucket_open_download_stream():打开新的下载流,您可以从中读取文件内容

  • mongoc_gridfs_bucket_download_to_stream():将整个文件写入现有下载流

您可以使用 mongoc_gridfs_bucket_open_download_stream() 函数创建下载流,从MongoDB 数据库下载文件。

此示例使用下载流来执行以下操作:

  • 调用 mongoc_gridfs_bucket_open_download_stream() 函数以选择具有指定 _id 值的GridFS文件并将其作为可读流打开

  • 调用 mongoc_stream_read() 函数以读取文件内容

  • 调用 mongoc_stream_close()mongoc_stream_destroy() 函数关闭并销毁指向该文件的下载流

char buf[512];
bson_value_t file_id;
file_id.value_type = BSON_TYPE_OID;
bson_oid_init_from_string (&file_id.value.v_oid, "66fb1b8ea0f84a74ee099e71");
bson_error_t error;
mongoc_stream_t *download_stream = mongoc_gridfs_bucket_open_download_stream (bucket, &file_id, &error);
if (!download_stream) {
fprintf (stderr, "Failed to create download stream: %s\n", error.message);
}
mongoc_stream_read (download_stream, buf, 1, 1, 0);
mongoc_stream_close (download_stream);
mongoc_stream_destroy (download_stream);

注意

如果存在多个具有相同文件名的文档, GridFS将流具有给定名称(由uploadDate字段确定)的最新文件。

您可以通过调用 mongoc_gridfs_bucket_download_to_stream() 函数将GridFS文件的内容下载到现有流。

此示例将执行以下动作:

  • 调用 mongoc_stream_file_new_for_path() 函数以在写入(O_RDWR)模式将位于 /path/to/output_file 的文件作为流打开

  • 将具有指定 _id 值的GridFS文件下载量到流

  • 调用 mongoc_stream_close()mongoc_stream_destroy() 函数以关闭并销毁文件流

mongoc_stream_t *file_stream = mongoc_stream_file_new_for_path ("/path/to/output_file", O_RDWR, 0);
bson_error_t error;
if (!file_stream) {
fprintf (stderr, "Error opening file stream: %s\n", error.message);
}
bson_value_t file_id;
file_id.value_type = BSON_TYPE_OID;
bson_oid_init_from_string (&file_id.value.v_oid, "66fb1b8ea0f84a74ee099e71");
if (!mongoc_gridfs_bucket_download_to_stream (bucket, &file_id, file_stream, &error)) {
fprintf (stderr, "Failed to download file: %s\n", error.message);
}
mongoc_stream_close (file_stream);
mongoc_stream_destroy (file_stream);

使用 mongoc_gridfs_bucket_delete_by_id() 函数从存储桶中删除文件的集合文档和关联的数据段。这实际上删除了该文件。

下面的示例展示了如何通过引用文件的 _id 字段来删除文件:

bson_error_t error;
bson_oid_t oid;
bson_oid_init_from_string (&oid, "66fb1b365fd1cc348b031b01");
if (!mongoc_gridfs_bucket_delete_by_id (bucket, &oid, &error)) {
fprintf (stderr, "Failed to delete file: %s\n", error.message);
}

注意

文件修订

mongoc_gridfs_bucket_delete_by_id() 函数一次仅支持删除一个文件。如果要删除每个文件修订版本,或上传时间不同但股票相同文件名的文件,请收集每个修订版本的 _id 值。然后,将每个 _id 值分别传递给 mongoc_gridfs_bucket_delete_by_id() 函数。

要学习;了解有关使用C驾驶员存储和检索大文件的更多信息,请参阅以下API文档:

后退

事务