适用于 PHP 的 AWS 开发工具包
开发人员指南
AWS 文档中描述的 AWS 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅中国的 AWS 服务入门

Amazon S3 Stream Wrapper 与AWS SDK for PHP版本 3

Amazon S3 Stream Wrapper 支持您使用内置 PHP 函数从 Amazon S3 存储和检索数据,这些函数包括 file_get_contentsfopencopyrenameunlinkmkdirrmdir

您需要注册 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。对于没有此级别权限的使用情形,我们建议您直接使用 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($steam, 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 Stream Wrapper 支持以下模式。

r

只读流,文件必须已存在。

w

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

a

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

x

只可写入的流。如果文件不存在将引发错误。

其他对象函数

Stream Wrappers 允许多种不同的内置 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()

检查 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 是否对应于文件或存储桶 (dir)。

file()

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

filemtime()

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

重命名()

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

注意

虽然 copy 一般与 Amazon S3 Stream Wrapper 配合使用,由于 PHP 中 copy 函数的内部原因,某些错误可能不会正确报告。我们建议您使用 AwsS3ObjectCopier 的实例作为替代。

使用存储桶

您修改和浏览 Amazon S3 存储桶的方式,与 PHP 允许的在您的文件系统中进行修改与遍历目录的方式类似。

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

mkdir('s3://bucket');

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

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

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

// Delete a bucket rmdir('s3://bucket');

注意

只有空存储桶才可删除。

列出存储桶的内容

可将 opendir()readdir()rewinddir()closedir() PHP 函数与 Amazon S3 Stream Wrapper 配合使用,遍历存储桶的内容。您可以将 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 的 RecursiveDirectoryIterator 以递归方式列出存储桶中的每个对象和前缀。

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

还可以使用 Aws\recursive_dir_iterator($path, $context = null) 函数以递归方式列出存储桶内容,这样可产生较少的 HTTP 请求。

<?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 的实例可用于缓存之前获得的文件统计数据。默认情况下,Stream Wrapper 使用内存中 LRU 缓存。