本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。
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() |
从存储桶中删除一个对象。
您可以传递
|
filesize() |
获取对象的大小。
|
is_file() |
检查 a URL 是否为文件。
|
file_exists() |
检查某个对象是否存在。
|
filetype() |
检查是否URL映射到文件或存储桶(目录)。 |
file() |
将对象内容加载到一些行中。您可以传递 |
filemtime() |
获取对象的最新修改日期。 |
rename() |
复制对象并删除原始版本,从而对对象重命名。您可以将 |
注意
尽管copy
通常适用于 Amazon S3 流包装器,但由于中copy
函数的内部结构,某些错误可能无法正确报告。PHP我们建议您改用 awss3 ObjectCopier 的实例。
使用存储桶和文件夹
使用 mkdir()
来使用存储桶
您可以创建和浏览 Amazon S3 存储桶,就像PHP允许您在文件系统上创建和遍历目录的方式一样。
以下是创建存储桶的示例。
mkdir('s3://amzn-s3-demo-bucket');
注意
2023 年 4 月,Amazon S3 自动启用了 S3 屏蔽公共访问权限,并对所有新创建的存储桶禁用了访问控制列表。此更改还会影响StreamWrapper
的mkdir
函数如何使用权限和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 ()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 'RecursiveDirectoryIterator
$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缓存。