Docs 菜单
Docs 主页
/ / /
PHP 库手册
/

存储大文件

在此页面上

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

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

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

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

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

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

当您创建新的GridFS存储桶时,该库会创建上述集合,并以默认存储桶名称fs作为前缀,除非您指定其他名称。该库还会对每个集合创建索引,以确保高效检索文件和相关元数据。如果GridFS存储桶不存在,则该库仅在执行第一次写入操作时才会创建该存储桶。仅当索引不存在且存储桶为空时,库才会创建索引。有关GridFS索引的更多信息,请参阅MongoDB Server手册中的GridFS索引

使用GridFS存储文件时,该库会将文件分割成较小的数据段,每个数据段由chunks 集合中的单独文档表示。它还在files 集合中创建一个文档,其中包含文件ID、文件名和其他文件元数据。您可以通过将流MongoDB PHP库以使用或创建新流并直接写入来上传文件。要学习;了解有关流的详情,请参阅 在PHP手册中。

查看下图,了解GridFS在将文件上传到存储桶时如何拆分文件:

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

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

要从GridFS存储或检索文件,请对数据库调用MongoDB\Database::selectGridFSBucket()方法。此方法访问现有存储桶,如果不存在,则创建新存储桶。

以下示例对db数据库调用selectGridFSBucket()方法:

$bucket = $client->db->selectGridFSBucket();

您可以通过将指定选项值的大量传递给selectGridFSBucket()方法来自定义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 261120.
Type: integer
readConcern
Specifies the read concern to use for bucket operations. The default value is the database's read concern.
Type: MongoDB\Driver\ReadConcern
readPreference
Specifies the read preference to use for bucket operations. The default value is the database's read preference.
Type: MongoDB\Driver\ReadPreference
writeConcern
Specifies the write concern to use for bucket operations. The default value is the database's write concern.
Type: MongoDB\Driver\WriteConcern

以下示例通过将大量传递给设置bucketName选项的selectGridFSBucket()来创建名为'myCustomBucket'的存储桶:

$custom_bucket = $client->db->selectGridFSBucket(
['bucketName' => 'myCustomBucket']
);

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

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

  • MongoDB\GridFS\Bucket::uploadFromStream():将现有流的内容上传到GridFS文件

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

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

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

  • 将大量参数中的metadata选项设置为openUploadStream()方法

  • 调用fwrite()方法以写入'my_file' ,流指向

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

$stream = $bucket->openUploadStream('my_file', [
'metadata' => ['contentType' => 'text/plain']
]);
fwrite($stream, 'Data to store');
fclose($stream);

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

此示例将执行以下动作:

  • 调用fopen()方法以在二进制读取 ( rb )模式将位于/path/to/input_file的文件作为流打开

  • 调用uploadFromStream()方法将流的内容上传到名为'new_file'的GridFS文件

$file = fopen('/path/to/input_file', 'rb');
$bucket->uploadFromStream('new_file', $file);

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

  • 文件的 _id

  • 文件的名称

  • 文件的长度/大小

  • 上传日期和时间

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

要从GridFS存储桶检索文件,请对MongoDB\GridFS\Bucket实例调用MongoDB\GridFS\Bucket::find()方法。该方法返回一个MongoDB\Driver\Cursor实例,您可以从该实例访问权限结果。要学习;了解有关MongoDB PHP库中Cursor对象的更多信息,请参阅从游标访问数据指南。

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

$files = $bucket->find();
foreach ($files as $file_doc) {
echo toJSON($file_doc), PHP_EOL;
}

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

注意

前面的示例调用toJSON()方法将文件元数据打印为扩展JSON,在以下代码中定义:

function toJSON(object $document): string
{
return MongoDB\BSON\Document::fromPHP($document)->toRelaxedExtendedJSON();
}

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

  • MongoDB\GridFS\Bucket::openDownloadStreamByName()MongoDB\GridFS\Bucket::openDownloadStream() :打开新的下载流,您可以从中读取文件内容

  • MongoDB\GridFS\Bucket::downloadToStream():将整个文件写入现有下载流

您可以使用MongoDB\GridFS\Bucket::openDownloadStreamByName()方法创建下载流,从MongoDB 数据库下载文件。

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

  • 选择在写入上传流示例中上传的名为'my_file'的GridFS文件,并将其作为可读流打开

  • 调用stream_get_contents()方法以读取'my_file'的内容

  • 打印文件内容

  • 调用fclose()方法关闭指向'my_file'的下载流

$stream = $bucket->openDownloadStreamByName('my_file');
$contents = stream_get_contents($stream);
echo $contents, PHP_EOL;
fclose($stream);

注意

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

或者可以使用 MongoDB\GridFS\Bucket::openDownloadStream() 方法将文件的 _id 字段作为参数:

$stream = $bucket->openDownloadStream(new ObjectId('66e0a5487c880f844c0a32b1'));
$contents = stream_get_contents($stream);
fclose($stream);

注意

GridFS流媒体API无法加载部分数据段。当下载流需要从数据块拉取一个MongoDB时,它会将整个数据块入内存。 255千字节的默认数据数据块大小通常已足够,但您可以减小数据数据块大小以减少内存开销,或在处理较大文件时增加数据数据块大小。有关设置数据数据块大小的更多信息,请参阅本页的自定义存储桶部分。

当您的存储桶包含多个股票相同文件名的文件时, GridFS默认文件最近上传的版本。为了区分同名的每个文件, GridFS为它们分配一个修订版本号,按上传时间排序。

原始文件修订号是0 ,下一个最新的文件修订号是1 。您还可以指定与修订的新近度相对应的负值。修订值-1引用最新修订版本, -2引用下一个最新修订版本。

您可以通过将选项大量传递给openDownloadStreamByName()方法并指定revision选项来指示GridFS下载特定的文件修订版。以下示例读取名为'my_file'的原始文件的内容,而不是最新修订的内容:

$stream = $bucket->openDownloadStreamByName('my_file', ['revision' => 0]);
$contents = stream_get_contents($stream);
fclose($stream);

您可以通过在存储桶上调用MongoDB\GridFS\Bucket::downloadToStream()方法,将GridFS文件的内容下载到现有流。

此示例将执行以下动作:

  • 调用fopen()方法以在二进制写入( wb )模式将位于/path/to/output_file的文件作为流打开

  • _id值为ObjectId('66e0a5487c880f844c0a32b1')的GridFS文件下载量到流

$file = fopen('/path/to/output_file', 'wb');
$bucket->downloadToStream(
new ObjectId('66e0a5487c880f844c0a32b1'),
$file,
);

使用 MongoDB\GridFS\Bucket::rename() 方法更新存储桶中 GridFS 文件的名称。您必须用文件的 _id 字段而不是文件名来指定要重命名的文件。

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

$bucket->rename(new ObjectId('66e0a5487c880f844c0a32b1'), 'new_file_name');

注意

文件修订

rename()方法一次仅支持更新一个文件的名称。如果要重命名每个文件修订版或上传时间不同但股票相同文件名的文件,请收集每个修订版的_id值。然后,将每个值分别传递给rename()方法。

使用MongoDB\GridFS\Bucket::delete()方法从存储桶中删除文件的集合文档和关联的数据段。 这实际上删除了该文件。 您必须用文件的_id字段而不是文件名来指定文件。

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

$bucket->delete(new ObjectId('66e0a5487c880f844c0a32b1'));

注意

文件修订

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

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

后退

执行事务