

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

# 使用 适用于 PHP 的 AWS SDK 版本 3 将目录传入和传出 Amazon S3
<a name="s3-transfer"></a>

您可以使用 适用于 PHP 的 AWS SDK 版本 3 中的`Transfer`类将整个目录上传到 Amazon S3 存储桶，并将整个存储桶下载到本地目录。

## 将本地目录上传到 Amazon S3
<a name="uploading-a-local-directory-to-s3"></a>

[https://docs.aws.amazon.com/aws-sdk-php/v3/api/class-Aws.S3.Transfer.html](https://docs.aws.amazon.com/aws-sdk-php/v3/api/class-Aws.S3.Transfer.html)对象执行传输。以下示例展示了如何将本地文件目录递归上传到 Amazon S3 存储桶。

```
// Create an S3 client.
$client = new \Aws\S3\S3Client([
    'region'  => 'us-west-2',
    'version' => '2006-03-01',
]);

// Where the files will be sourced from.
$source = '/path/to/source/files';

// Where the files will be transferred to.
$dest = 's3://bucket';

// Create a transfer object.
$directoryTransfer = new \Aws\S3\Transfer($client, $source, $dest);

// Perform the transfer synchronously.
$directoryTransfer->transfer();
```

在此示例中，我们创建了一个 Amazon S3 客户端，创建了一个 `Transfer` 对象，并执行了同步传输。

前面的示例演示了执行传输所需的最小代码量。`Transfer`对象也可以异步执行传输，并具有各种配置选项，可用于自定义传输。

您可以通过在 `s3://` URI 中提供键前缀，将本地文件上传到 Amazon S3 存储桶的“子文件夹”。以下示例将磁盘上的本地文件上传到 `bucket` 存储桶，并将文件存储在 `foo` 键前缀下。

```
$source = '/path/to/source/files';
$dest = 's3://bucket/foo';
$directoryTransfer = new \Aws\S3\Transfer($client, $source, $dest);
$directoryTransfer->transfer();
```

## 下载 Amazon S3 存储桶
<a name="downloading-an-s3-bucket"></a>

您可以通过将 `$source` 参数指定为 Amazon S3 URI（例如 `s3://bucket`）并将 `$dest` 参数指定为本地目录的路径，从而将 Amazon S3 存储桶递归下载到磁盘上的本地目录。

```
// Where the files will be sourced from.
$source = 's3://bucket';

// Where the files will be transferred to.
$dest = '/path/to/destination/dir';

$directoryTransfer = new \Aws\S3\Transfer($client, $source, $dest);
$directoryTransfer->transfer();
```

**注意**  
下载存储桶中的对象时，SDK 会自动创建所有必要的目录。

您可以通过在 Amazon S3 URI 中于存储桶后面添加键前缀，仅下载存储在“虚拟文件夹”下的对象。以下示例仅下载存储在给定存储桶的“/foo”键前缀下的文件。

```
$source = 's3://bucket/foo';
$dest = '/path/to/destination/dir';
$directoryTransfer = new \Aws\S3\Transfer($client, $source, $dest);
$directoryTransfer->transfer();
```

## 配置
<a name="configuration"></a>

`Transfer` 对象构造函数接受以下参数。

** `$client` **  
`Aws\ClientInterface` 对象用于执行传输。

** `$source`（字符串 \$1 `Iterator`）**  
正在传输的源数据。这可以指向本地磁盘上的路径（例如 `/path/to/files`）或 Amazon S3 存储桶（例如 `s3://bucket`）。`s3://` URI 还可能包含可用于仅传输通用前缀下的对象的键前缀。  
如果 `$source` 参数为 Amazon S3 URI，则 `$dest` 参数必须是一个本地目录（反之亦然）。  
除了提供字符串值之外，您还可以提供生成绝对文件名的 `\Iterator` 对象。如果提供`\Iterator`对象，则**必须在**`$options`关联数组中提供一个`base_dir`选项。

** `$dest` **  
文件传输目的地。如果 `$source` 参数是磁盘上的本地路径，则 `$dest` 必须为 Amazon S3 存储桶 URI（例如 `s3://bucket`）。如果 `$source` 参数是 Amazon S3 存储桶 URI，则 `$dest` 参数必须为磁盘上的本地路径。

** `$options` **  
传输选项的关联数组。以下传输选项是有效的：    
**`add_content_md5` (bool)**  
设置`true`为可计算上传的 MD5 校验和。  
** `base_dir`（字符串）**  
源的基本目录（如果 `$source` 为迭代器）。如果 `$source` 选项不是数组，则此选项将被忽略。  
** `before`（可调用）**  
每次传输前要调用的回调。此回调应具有类似 `function (Aws\Command $command) {...}` 的函数签名。提供的命令将是 `GetObject`、`PutObject`、`CreateMultipartUpload`、`UploadPart` 或 `CompleteMultipartUpload` 命令。  
** `mup_threshold` (int)**  
字节大小，应使用分段上传而不是 `PutObject`。默认值为 `16777216`（16 MB）。  
** `concurrency`（整数，默认值=5）**  
并发上传的文件数。理想的并发值会有所不同，具体取决于正在上传的文件数以及每个文件的平均大小。通常，更高的并发度对较小文件有利，对较大文件则不然。  
** `debug` (bool)**  
设置为 `true` 可打印输出调试信息用于传输。设置为 `fopen()` 资源可写入特定流，而不是写入 STDOUT。

## 异步传输
<a name="async-transfers"></a>

`Transfer` 对象是 `GuzzleHttp\Promise\PromisorInterface` 的实例。这意味着传输可以异步发生，并通过调用对象的 `promise` 方法启动。

```
$source = '/path/to/source/files';
$dest = 's3://bucket';
$directoryTransfer = new \Aws\S3\Transfer($client, $source, $dest);

// Initiate the transfer and get a promise.
$promise = $directoryTransfer->promise();

// Do something when the transfer is complete using the then() method.
$promise->then(function () {
    echo 'Done!';
});
```

如果有任何文件传输失败，则承诺将被拒绝。您可以使用 Promise 的 `otherwise` 方法以异步方式处理失败的传输。出现错误时，`otherwise` 函数接受要调用的回调。回调接受拒绝`$reason`的，通常是的实例`Aws\Exception\AwsException`（尽管可以将**任何**类型的值传递给回调）。

```
$promise->otherwise(function ($reason) {
    echo 'Transfer failed: ';
    var_dump($reason);
});
```

由于 `Transfer` 对象返回一个 Promise，这些传输可以与其他异步 Promise 同时进行。

## 自定义目录传输
<a name="customizing-the-transfer-manager-s-commands"></a>

通过向构造函数添加回调，可以自定义其`Transfer`执行的选项。

```
$uploader = new Transfer($s3Client, $source, $dest, [
    'before' => function (\Aws\Command $command) {
        // Commands can vary for multipart uploads, so check which command
        // is being processed.
        if (in_array($command->getName(), ['PutObject', 'CreateMultipartUpload'])) {
            // Set custom cache-control metadata.
            $command['CacheControl'] = 'max-age=3600';
            // Apply a canned ACL.
            $command['ACL'] = strpos($command['Key'], 'CONFIDENTIAL') ### false
                ? 'public-read'
                : 'private';
        }
    },
]);
```