AWS SDK for PHP 版本 3 的 Amazon S3 直播封装器 - AWS SDK for PHP

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

AWS SDK for PHP 版本 3 的 Amazon S3 直播封装器

Amazon S3 流包装器允许您使用内置PHP函数(例如、、、、、、和)存储和rmdir检索来自 Amazon S3 的数据。file_get_contents fopen copy rename unlink mkdir

您需要注册 Amazon S3 Stream Wrapper 才可使用。

$client = new Aws\S3\S3Client([/** options **/]); // Register the stream wrapper from an S3Client object $client->registerStreamWrapper();

这样您就可以使用 s3:// 协议来访问 Amazon S3 中存储的存储桶和对象。Amazon S3 Stream Wrapper 接受包含存储桶名称的字符串,后跟正斜杠和可选的对象键或前缀:s3://<bucket>[/<key-or-prefix>]

注意

Stream Wrapper 可处理您至少拥有读取权限的对象和存储桶。这就意味着,您的用户应有权针对任何需要交互的存储桶执行 ListBucket,并针对任何需要交互的对象执行 GetObject。对于不具有此级别权限的使用情形,建议您直接使用 Amazon S3 客户端操作。

下载数据

您可以使用 file_get_contents 获取对象内容。但使用此功能要小心,它会将对象的全部内容载入内存。

// Download the body of the "key" object in the "bucket" bucket $data = file_get_contents('s3://bucket/key');

如果处理较大文件或需要从 Amazon S3 流式传输数据,请使用 fopen()

// Open a stream in read-only mode if ($stream = fopen('s3://bucket/key', 'r')) { // While the stream is still open while (!feof($stream)) { // Read 1,024 bytes from the stream echo fread($stream, 1024); } // Be sure to close the stream resource when you're done with it fclose($stream); }
注意

只有调用 fflush 才会返回文件写入错误。如果调用了未刷新的 fclose,不会返回这些错误。如果 fclose 关闭了流,它的返回值将为 true;无论其内部 fflush 是否会响应任何错误。file_put_contents由于PHP实现方式的原因,调用时也不会返回这些错误。

打开可搜寻的流

以“r”模式打开的流仅允许读取流中的数据,默认情况下不可搜寻。这样数据才能够真正以流式处理的方式从 Amazon S3 下载,之前读取的字节不需要缓冲到内存中。如果需要对流进行搜寻,可以将 seekable 传递到函数的流上下文选项

$context = stream_context_create([ 's3' => ['seekable' => true] ]); if ($stream = fopen('s3://bucket/key', 'r', false, $context)) { // Read bytes from the stream fread($stream, 1024); // Seek back to the beginning of the stream fseek($stream, 0); // Read the same bytes that were previously read fread($stream, 1024); fclose($stream); }

“打开可搜寻的流”支持您搜寻之前读取的字节。您不可跳转到尚未从远程服务器读取的字节。为了允许调用之前读取的数据,使用流装饰器在PHP临时流中缓冲数据。如果缓存数据量超过 2 MB,临时流中的数据会从内存传输到磁盘中。在使用 seekable 流上下文设置从 Amazon S3 下载大文件时,请留意这一点。

上传数据

您可以使用 file_put_contents() 来将数据上传到 Amazon S3。

file_put_contents('s3://bucket/key', 'Hello!');

您可以结合使用 fopen() 和“w”、“x”或“a”流访问模式来流式传输数据,从而上传较大的文件。Amazon S3 Stream Wrapper 支持同时读取和写入流(例如“r+”、“w+”等)。这是因为该HTTP协议不允许同时读取和写入。

$stream = fopen('s3://bucket/key', 'w'); fwrite($stream, 'Hello!'); fclose($stream);
注意

Amazon S3 需要在发送请求负载之前指定内容长度标题。因此,PutObject操作中要上传的数据在内部使用PHP临时流进行缓冲,直到流被刷新或关闭。

注意

只有调用 fflush 才会返回文件写入错误。如果调用了未刷新的 fclose,不会返回这些错误。如果 fclose 关闭了流,它的返回值将为 true;无论其内部 fflush 是否会响应任何错误。file_put_contents由于PHP实现方式的原因,调用时也不会返回这些错误。

fopen 模式

PHP的 fopen () 函数要求你指定一个$mode选项。mode 选项指定数据是否可在流中进行读写,以及打开流时文件是否必须存在。

对于以 Amazon S3 对象为目标的流,Amazon S3 Stream Wrapper 支持以下模式。

r

只读流,对象必须已存在。

w

只可写入的流。如果对象已存在,则将覆盖该对象。

a

只可写入的流。如果对象已存在,则会将它下载到临时流中,并且对流的任何写入操作将追加到之前上传的数据后面。

x

只可写入的流。如果对象已存在,将引发错误。

其他对象函数

流包装器允许许多不同的内置PHP函数与 Amazon S3 等自定义系统配合使用。Amazon S3 Stream Wrapper 允许您针对存储在 Amazon S3 中的对象执行以下函数。

unlink()

从存储桶中删除一个对象。

// Delete an object from a bucket unlink('s3://bucket/key');

您可以传递 DeleteObject 操作的任何可用选项,修改对象的删除方式(例如指定具体的对象版本)。

// Delete a specific version of an object from a bucket unlink('s3://bucket/key', stream_context_create([ 's3' => ['VersionId' => '123'] ]);

filesize()

获取对象的大小。

// Get the Content-Length of an object $size = filesize('s3://bucket/key', );

is_file()

检查 a URL 是否为文件。

if (is_file('s3://bucket/key')) { echo 'It is a file!'; }

file_exists()

检查某个对象是否存在。

if (file_exists('s3://bucket/key')) { echo 'It exists!'; }

filetype()

检查是否URL映射到文件或存储桶(目录)。

file()

将对象内容加载到一些行中。您可以传递 GetObject 操作的任何可用选项,修改文件的下载方式。

filemtime()

获取对象的最新修改日期。

rename()

复制对象并删除原始版本,从而对对象重命名。您可以将 CopyObjectDeleteObject 操作的可用选项传递到流上下文参数,修改复制和删除对象的方式。

注意

尽管copy通常适用于 Amazon S3 流包装器,但由于中copy函数的内部结构,某些错误可能无法正确报告。PHP我们建议您改用 awss3 ObjectCopier 的实例。

使用存储桶和文件夹

使用 mkdir() 来使用存储桶

您可以创建和浏览 Amazon S3 存储桶,就像PHP允许您在文件系统上创建和遍历目录的方式一样。

以下是创建存储桶的示例。

mkdir('s3://amzn-s3-demo-bucket');
注意

2023 年 4 月,Amazon S3 自动启用了 S3 屏蔽公共访问权限,并对所有新创建的存储桶禁用了访问控制列表。此更改还会影响StreamWrappermkdir函数如何使用权限和ACLs. 更多信息可参见这篇新增内容一 AWS 文

您可以使用CreateBucket操作可用的参数将流上下文选项传递给该mkdir()方法,以修改存储桶的创建方式。

// Create a bucket in the EU (Ireland) Region mkdir('s3://amzn-s3-demo-bucket', 0500, true, stream_context_create([ 's3' => ['LocationConstraint' => 'eu-west-1'] ]));

您可以使用 rmdir() 函数删除存储桶。

// Delete a bucket rmdir('s3://amzn-s3-demo-bucket);
注意

只有空存储桶才可删除。

使用 mkdir() 来使用文件夹

创建存储桶后,您可以使用 mkdir() 来创建对象,这些对象可用作文件夹,就像在文件系统中一样。

以下代码段将名为 “my-folder” 的文件夹对象添加到名为 “amzn-s3-demo-bucket” 的现有存储桶中。使用正斜杠 (/) 字符将文件夹对象名称与存储桶名称和任何其他文件夹名称分开。

mkdir('s3://amzn-s3-demo-bucket/my-folder')

关于 2023 年 4 月之后权限变更的上一个注释也会在您创建文件夹对象时发挥作用。这篇博客文章包含有关如何在需要时调整权限的信息。

使用 rmdir() 函数删除空文件夹对象,如下面的代码段所示。

rmdir('s3://amzn-s3-demo-bucket/my-folder')

列出存储桶的内容。

您可以将 opendir ()readdir ()、rewinddir () 和 closedir () 函数与 PHP Amazon S3 流包装器一起使用来遍历存储桶的内容。您可以将ListObjects操作可用的参数作为自定义流上下文选项传递给opendir()函数,以修改对象的列出方式。

$dir = "s3://bucket/"; if (is_dir($dir) && ($dh = opendir($dir))) { while (($file = readdir($dh)) !== false) { echo "filename: {$file} : filetype: " . filetype($dir . $file) . "\n"; } closedir($dh); }

您可以使用 PHP 'RecursiveDirectoryIterators递归列出存储桶中的每个对象和前缀。

$dir = 's3://bucket'; $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir)); foreach ($iterator as $file) { echo $file->getType() . ': ' . $file . "\n"; }

递归列出存储桶内容从而减少HTTP请求量的另一种方法是使用函数。Aws\recursive_dir_iterator($path, $context = null)

<?php require 'vendor/autoload.php'; $iter = Aws\recursive_dir_iterator('s3://bucket/key'); foreach ($iter as $filename) { echo $filename . "\n"; }

流上下文选项

您可以通过传递自定义流上下文选项,自定义 Stream Wrapper 使用的客户端,或用于缓存之前加载的存储桶和键信息的缓存。

Stream Wrapper 针对每个操作支持以下流上下文选项。

client

Aws\AwsClientInterface 对象,用于执行命令。

cache

Aws\CacheInterface 的实例可用于缓存之前获得的文件统计数据。默认情况下,流包装器使用内存中的LRU缓存。