

# 使用 S3 版本控制保留对象的多个版本
<a name="Versioning"></a>

Amazon S3 中的版本控制是在相同的存储桶中保留对象的多个变量的方法。对于存储桶中存储的每个对象，您可以使用 S3 版本控制功能来保留、检索和还原它们的各个版本。使用版本控制能够更加轻松地从用户意外操作和应用程序故障中恢复数据。为存储桶启用版本控制后，如果 Amazon S3 同时收到针对同一对象的多个写入请求，它会存储所有对象。

启用了版本控制的存储桶可以协助您恢复因意外删除或覆盖操作而失去的对象。例如，如果您删除对象，Amazon S3 会插入删除标记，而不是永久删除该对象。删除标记将成为当前对象版本。如果覆盖对象，则会导致存储桶中出现新的对象版本。您始终可以恢复以前的版本。有关更多信息，请参阅 [从启用了版本控制的存储桶中删除对象版本](DeletingObjectVersions.md)。

默认情况下，S3 版本控制在存储桶上处于禁用状态，您必须明确启用它。有关更多信息，请参阅 [在存储桶上启用版本控制](manage-versioning-examples.md)。

**注意**  
SOAP API 不支持 S3 版本控制。HTTP 上的 SOAP 支持已弃用，但是仍可在 HTTPS 上使用。SOAP 不支持新增的 Amazon S3 功能。
对于存储和传输的每个对象版本，都适用正常 Amazon S3 费率。对象的每个版本都是完整的对象；它并非只是与上一版本有所不同。因此，如果您存储了三个版本的对象，则会收取您三个对象的费用。

## 不受版本控制、启用了版本控制和已暂停版本控制的存储桶
<a name="versioning-states"></a>

存储桶可能处于以下三种状态之一：
+ 不受版本控制（默认）
+ 已启用版本控制
+ 已暂停版本控制

您可以在存储桶级别启用和暂停版本控制。一旦您对存储桶启用了版本控制，它将无法返回到不受版本控制状态。但是，您可以在该存储桶上*暂停*版本控制。

版本控制状态将应用到该存储桶中的所有（不是某些）对象。当您在存储桶中启用版本控制功能时，所有新对象都将受版本控制，并为其指定唯一的版本 ID。此后，在启用版本控制功能时，存储桶中已存在的对象将*始终*受版本控制，并在以后的请求修改时为其提供唯一的版本 ID。请注意以下几点：
+ 在您设置版本控制状态之前存储在存储桶中的对象的版本 ID 为 `null`。启用版本控制时，存储桶中的现有对象不会更改。更改的是 Amazon S3 在以后的请求中处理这些对象的方式。有关更多信息，请参阅 [使用启用版本控制的存储桶中的对象](manage-objects-versioned-bucket.md)。
+ 存储桶拥有者（或任何具有适当权限的用户）可以暂停版本控制以停止累积对象版本。暂停版本控制时，存储桶中的现有对象不会更改。更改的是 Amazon S3 在以后的请求中处理对象的方式。有关更多信息，请参阅 [使用已暂停版本控制的存储桶中的对象](VersionSuspendedBehavior.md)。

## 将 S3 版本控制与 S3 生命周期结合使用
<a name="versioning-lifecycle"></a>

要自定义您的数据保留方法和控制存储成本，请将对象版本控制与 S3 生命周期结合使用。有关更多信息，请参阅 [管理对象的生命周期](object-lifecycle-mgmt.md)。有关使用 AWS 管理控制台、AWS CLI、AWS SDK 或 REST API 创建 S3 生命周期配置的信息，请参阅[在存储桶上设置 S3 生命周期配置](how-to-set-lifecycle-configuration-intro.md)。

**重要**  
如果您在不受版本控制的存储桶中具有对象到期生命周期配置，并且希望在启用版本控制时保持相同的永久删除行为，则必须添加非当前版本到期策略。非当前版本到期生命周期配置将管理在启用版本控制的存储桶中删除非当前对象版本的行为。（启用版本控制的存储桶会维护一个当前对象版本，以及零个或更多非当前对象版本。） 有关更多信息，请参阅 [在存储桶上设置 S3 生命周期配置](how-to-set-lifecycle-configuration-intro.md)。

有关使用 S3 版本控制的信息，请参阅以下主题。

**Topics**
+ [不受版本控制、启用了版本控制和已暂停版本控制的存储桶](#versioning-states)
+ [将 S3 版本控制与 S3 生命周期结合使用](#versioning-lifecycle)
+ [S3 版本控制的工作原理](versioning-workflows.md)
+ [在存储桶上启用版本控制](manage-versioning-examples.md)
+ [配置 MFA 删除](MultiFactorAuthenticationDelete.md)
+ [使用启用版本控制的存储桶中的对象](manage-objects-versioned-bucket.md)
+ [使用已暂停版本控制的存储桶中的对象](VersionSuspendedBehavior.md)
+ [版本控制故障排除](troubleshooting-versioning.md)

# S3 版本控制的工作原理
<a name="versioning-workflows"></a>

您可以使用 S3 版本控制将对象的多个版本保存在一个存储桶中，以便您能够还原意外删除或覆盖的对象。例如，如果您将 S3 版本控制应用于存储桶，则会发生以下变化：
+ 如果删除对象（而不是永久移除此对象），则 Amazon S3 会插入删除标记，它将成为当前对象版本。然后，您可以恢复以前的版本。有关更多信息，请参阅 [从启用了版本控制的存储桶中删除对象版本](DeletingObjectVersions.md)。
+ 如果覆盖对象，则 Amazon S3 会在存储桶中添加新的对象版本。之前的版本保留在存储桶中，成为非当前版本。您可以还原以前的版本。

**注意**  
对于存储和传输的每个对象版本，都适用正常 Amazon S3 费率。对象的每个版本都是完整的对象；它与以前的版本没有什么区别。因此，如果您存储了三个版本的对象，则会收取您三个对象的费用。

您创建的每个 S3 存储桶都具有关联的 *versioning* 子资源。（有关更多信息，请参阅 [通用存储桶配置选项](UsingBucket.md#bucket-config-options-intro)。） 默认情况下，您的存储桶*不受版本控制*，且对子资源进行版本控制会存储空的版本控制配置，如下所示。

```
<VersioningConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> 
</VersioningConfiguration>
```

要启用版本控制，您可以向 Amazon S3 发送请求，在请求中指定包含 `Enabled` 状态的版本控制配置。

```
<VersioningConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> 
  <Status>Enabled</Status> 
</VersioningConfiguration>
```

要暂停版本控制，请将状态值设置为 `Suspended`。

**注意**  
当您首次对存储桶启用版本控制时，可能只需很短的时间即可完全传播更改。当此更改传播时，在对启用版本控制后创建或更新的对象发出请求时，您可能会遇到间歇性 `HTTP 404 NoSuchKey` 错误。我们建议您在启用版本控制后等待 15 分钟，然后再对存储桶中的对象发出写入操作（`PUT` 或 `DELETE`）。

存储桶拥有者和所有获得授权的 AWS Identity and Access Management（IAM）用户都可以启用版本控制。创建存储桶的存储桶拥有者为 AWS 账户。有关权限的更多信息，请参阅 [Amazon S3 的身份和访问管理](security-iam.md)。

有关使用 AWS 管理控制台、AWS Command Line Interface（AWS CLI）或 REST API 启用和禁用 S3 版本控制的更多信息，请参阅[在存储桶上启用版本控制](manage-versioning-examples.md)。

**Topics**
+ [版本 ID](#version-ids)
+ [版本控制工作流程](#versioning-workflows-examples)

## 版本 ID
<a name="version-ids"></a>

如果您为存储桶启用版本控制，Amazon S3 会自动为要存储的对象生成唯一版本 ID。例如，在一个存储桶中，您可以拥有两个具有相同键（对象名称）的对象，但版本 ID 不同，例如 `photo.gif`（版本 111111）和 `photo.gif`（版本 121212）。

![\[图中描述了一个启用了版本控制的存储桶，该存储桶有两个具有相同键但版本 ID 不同的对象。\]](http://docs.aws.amazon.com/zh_cn/AmazonS3/latest/userguide/images/versioning_Enabled.png)


无论 S3 版本控制是否启用，每个对象都有一个版本 ID。如果未启用 S3 版本控制，Amazon S3 将版本 ID 的值设置为 `null`。如果您启用 S3 版本控制，Amazon S3 会为对象分配版本 ID 值。此值将该对象与同一个键的其他版本区分开来。

在现有存储桶上启用 S3 版本控制时，已存储在存储桶中的对象将保持不变。版本 ID（`null`）、内容和权限保持不变。启用 S3 版本控制后，添加到存储桶的每个对象都会获得一个版本 ID，该 ID 将此版本与同一个键的其他版本区分开来。

Amazon S3 仅生成版本 ID，不能编辑它们。版本 ID 是 Unicode、UTF-8 编码、URL 就绪、不透明的字符串，长度不超过 1,024 字节。以下是示例：

`3sL4kqtJlcpXroDTDmJ+rmSpXd3dIbrHY+MTRCxf3vjVBH40Nr8X8gdRQBpUMLUo`

**注意**  
为简单起见，本主题中的其他示例使用更短的 ID。



## 版本控制工作流程
<a name="versioning-workflows-examples"></a>

当您在启用版本控制的存储桶中通过 `PUT` 放入对象时，不会覆盖非当前版本。如下图所示，当将 `photo.gif` 的新版本 `PUT` 到一个已经包含同名对象的存储桶中时，会发生以下行为：
+ 原始对象（ID = 111111）保留在存储桶中。
+ Amazon S3 生成一个新的版本 ID（121212），并将这个较新版本的对象添加到存储桶中。

![\[描述在 PUT 对象（位于已启用版本控制的存储桶中）时 S3 版本控制的工作原理的图。\]](http://docs.aws.amazon.com/zh_cn/AmazonS3/latest/userguide/images/versioning_PUT_versionEnabled3.png)


使用此功能，如果对象被意外覆盖或删除，则可以检索对象的先前版本。

当 `DELETE` 对象时，所有版本都将保留在存储桶中，而 Amazon S3 将插入删除标记，如下图所示。

![\[图中显示了删除标记插入。\]](http://docs.aws.amazon.com/zh_cn/AmazonS3/latest/userguide/images/versioning_DELETE_versioningEnabled.png)


删除标记将成为对象的当前版本。默认情况下，`GET` 请求将检索最新存储的版本。在当前版本为删除标记时，执行 `GET Object` 请求将返回 `404 Not Found` 错误，如下图所示。

![\[图中显示了对删除标记的 GetObject 调用返回 404（未找到）错误。\]](http://docs.aws.amazon.com/zh_cn/AmazonS3/latest/userguide/images/versioning_DELETE_NoObjectFound.png)


但是，您可以通过指定对象版本 ID，通过 `GET` 获取非当前版本的对象。在下图中，`GET` 特定对象版本 111111。即使该对象版本不是当前版本，Amazon S3 也会返回它。

有关更多信息，请参阅 [从启用了版本控制的存储桶中检索对象版本](RetrievingObjectVersions.md)。

![\[描述在启用版本控制的存储桶中 GET 非当前版本时 S3 版本控制的工作原理的图。\]](http://docs.aws.amazon.com/zh_cn/AmazonS3/latest/userguide/images/versioning_GET_Versioned3.png)


您可以通过指定要删除的版本来永久删除对象。只有 Amazon S3 存储桶的拥有者或者授权的 IAM 用户才能永久删除某个版本。如果您的 `DELETE` 操作指定了 `versionId`，则会永久删除该对象版本，Amazon S3 不会插入删除标记。

![\[图中显示了 DELETE versionId 如何永久删除特定对象版本。\]](http://docs.aws.amazon.com/zh_cn/AmazonS3/latest/userguide/images/versioning_DELETE_versioningEnabled2.png)


您可以通过配置存储桶来启用多重身份验证（MFA）删除，从而提升安全性。对存储桶启用 MFA 删除时，存储桶拥有者必须在任何请求中包含两种形式的身份验证，以删除版本或更改存储桶的版本控制状态。有关更多信息，请参阅 [配置 MFA 删除](MultiFactorAuthenticationDelete.md)。

### 何时为对象创建新版本？
<a name="versioning-workflows-new-versions"></a>

仅当您 `PUT` 新对象时，才会创建对象的新版本。请注意，某些操作（如 `CopyObject`）通过实现 `PUT` 操作来发挥作用。

某些修改当前对象的操作不会创建新版本，因为它们没有 `PUT` 新对象。这包括更改对象上的标签等操作。

**重要**  
如果您注意到，在对存储桶启用 S3 版本控制后，Amazon S3 对该存储桶的 `PUT` 或 `DELETE` 对象请求收到的 HTTP 503（服务不可用）响应数量显著增加，那么该存储桶中可能有一个或多个对象有数以百万计的版本。有关更多信息，请参阅[版本控制故障排除](troubleshooting-versioning.md)的“S3 版本控制”一节。

# 在存储桶上启用版本控制
<a name="manage-versioning-examples"></a>

您可以使用 S3 版本控制在一个存储桶中保留对象的多个版本。本部分提供了如何使用控制台、REST API、AWS SDK 和 AWS Command Line Interface（AWS CLI）在存储桶上启用版本控制的示例。

**注意**  
首次在存储桶上启用版本控制后，更改可能需要长达 15 分钟才能在 S3 系统中完全传播。在此期间，对启用版本控制后创建或更新的对象的 `GET` 请求可能会导致 `HTTP 404 NoSuchKey` 错误。我们建议在启用版本控制后等待 15 分钟，然后再对存储桶中的对象执行任何写入操作（`PUT` 或 `DELETE`）。此等待期有助于避免在对象可见性和版本跟踪方面可能出现的问题。

有关 S3 版本控制的更多信息，请参阅[使用 S3 版本控制保留对象的多个版本](Versioning.md)。有关使用已启用版本控制的存储桶中的对象的信息，请参阅 [使用启用版本控制的存储桶中的对象](manage-objects-versioned-bucket.md)。

要了解有关如何使用 S3 版本控制保护数据的更多信息，请参阅[教程：使用 S3 版本控制、S3 对象锁定和 S3 复制保护 Amazon S3 上的数据免遭意外删除或应用程序错误](https://aws.amazon.com/getting-started/hands-on/protect-data-on-amazon-s3/?ref=docs_gateway/amazons3/manage-versioning-examples.html)。

您创建的每个 S3 存储桶都具有关联的 *versioning* 子资源。（有关更多信息，请参阅 [通用存储桶配置选项](UsingBucket.md#bucket-config-options-intro)。） 默认情况下，您的存储桶*不受版本控制*，且对子资源进行版本控制会存储空的版本控制配置，如下所示。

```
<VersioningConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> 
</VersioningConfiguration>
```

要启用版本控制，您可以向 Amazon S3 发送一个请求，在请求中指定包含状态的版本控制配置。

```
<VersioningConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> 
  <Status>Enabled</Status> 
</VersioningConfiguration>
```

要暂停版本控制，请将状态值设置为 `Suspended`。

存储桶拥有者和所有授权用户都可以启用版本控制。存储桶拥有者是创建存储存储桶的 AWS 账户（根账户）。有关许可的更多信息，请参阅[Amazon S3 的身份和访问管理](security-iam.md)。

以下部分提供了有关使用控制台、AWS CLI 和 AWS SDK 启用 S3 版本控制的更多详细信息。

## 使用 S3 控制台
<a name="enable-versioning"></a>

请按照以下步骤使用 AWS 管理控制台 在 S3 存储桶上启用版本控制。

**在 S3 通用存储桶上启用或禁用版本控制**

1. 登录到 AWS 管理控制台，然后通过以下网址打开 Amazon S3 控制台：[https://console.aws.amazon.com/s3/](https://console.aws.amazon.com/s3/)。

1. 在左侧导航窗格中，选择**通用存储桶**。

1. 在存储桶列表中，选择要为其启用版本控制的存储桶的名称。

1. 请选择**属性**。

1. 在**存储桶版本控制**下，请选择**编辑**。

1. 请选择 **Suspend (暂停)** 或 **Enable (启用)**，然后选择 **Save changes (保存更改)**。

**注意**  
您可以将 AWS Multi-Factor Authentication (MFA) 与版本控制结合使用。将 MFA 与版本控制结合使用时，您必须提供 AWS 账户的访问密钥和账户 MFA 设备中的有效代码，才能永久删除对象版本或暂停或重新激活版本控制。  
要将 MFA 与版本控制结合使用，请启用 `MFA Delete`。但是，您无法使用 AWS 管理控制台 启用 `MFA Delete`。您必须使用 AWS Command Line Interface (AWS CLI) 或 API。有关更多信息，请参阅 [配置 MFA 删除](MultiFactorAuthenticationDelete.md)。

## 使用 AWS CLI
<a name="manage-versioning-examples-cli"></a>

以下示例在 S3 通用存储桶上启用版本控制。

```
aws s3api put-bucket-versioning --bucket amzn-s3-demo-bucket1 --versioning-configuration Status=Enabled
```

以下示例在存储桶上为物理 MFA 设备启用 S3 版本控制和多重身份验证（MFA）删除。对于物理 MFA 设备，在 `--mfa` 参数中，传递 MFA 设备序列号、空格字符和身份验证设备上显示的值的串联。

```
aws s3api put-bucket-versioning --bucket amzn-s3-demo-bucket1 --versioning-configuration Status=Enabled,MFADelete=Enabled --mfa "SerialNumber 123456"
```

以下示例在存储桶上为虚拟 MFA 设备启用 S3 版本控制和多重身份验证（MFA）删除。对于虚拟 MFA 设备，在 `--mfa` 参数中，传递 MFA 设备 ARN、空格字符和身份验证设备上显示的值的串联。

```
aws s3api put-bucket-versioning --bucket amzn-s3-demo-bucket1 --versioning-configuration Status=Enabled,MFADelete=Enabled --mfa "arn:aws:iam::account-id:mfa/root-account-mfa-device 123789"
```

**注意**  
使用 MFA 删除需要获得批准的物理或虚拟身份验证设备。有关在 Amazon S3 中使用 MFA 删除的更多信息，请参阅[配置 MFA 删除](MultiFactorAuthenticationDelete.md)。

有关使用 AWS CLI 启用版本控制的更多信息，请参阅《AWS CLI 命令参考》**中的 [put-bucket-versioning](https://awscli.amazonaws.com/v2/documentation/api/latest/reference/s3api/put-bucket-versioning.html)。

## 使用 AWS SDK
<a name="manage-versioning-examples-sdk"></a>

以下示例在存储桶上启用版本控制，然后使用 适用于 Java 的 AWS SDK 和 适用于 .NET 的 AWS SDK 检索版本控制状态。有关使用其他 AWS SDK 的信息，请参阅 [AWS 开发人员中心](https://aws.amazon.com/code/)。

------
#### [ .NET ]

有关设置和运行代码示例的信息，请参阅《适用于 .NET 的 AWS SDK 开发人员指南》**中的[适用于 .NET 的 AWS SDK 入门](https://docs.aws.amazon.com/sdk-for-net/latest/developer-guide/net-dg-setup.html)。

```
using System;
using Amazon.S3;
using Amazon.S3.Model;

namespace s3.amazon.com.rproxy.govskope.ca.docsamples
{
    class BucketVersioningConfiguration
    {
        static string bucketName = "*** bucket name ***";

        public static void Main(string[] args)
        {
            using (var client = new AmazonS3Client(Amazon.RegionEndpoint.USEast1))
            {
                try
                {
                    EnableVersioningOnBucket(client);
                    string bucketVersioningStatus = RetrieveBucketVersioningConfiguration(client);
                }
                catch (AmazonS3Exception amazonS3Exception)
                {
                    if (amazonS3Exception.ErrorCode != null &&
                        (amazonS3Exception.ErrorCode.Equals("InvalidAccessKeyId")
                        ||
                        amazonS3Exception.ErrorCode.Equals("InvalidSecurity")))
                    {
                        Console.WriteLine("Check the provided AWS Credentials.");
                        Console.WriteLine(
                        "To sign up for service, go to http://aws.amazon.com/s3");
                    }
                    else
                    {
                        Console.WriteLine(
                         "Error occurred. Message:'{0}' when listing objects",
                         amazonS3Exception.Message);
                    }
                }
            }

            Console.WriteLine("Press any key to continue...");
            Console.ReadKey();
        }

        static void EnableVersioningOnBucket(IAmazonS3 client)
        {

                PutBucketVersioningRequest request = new PutBucketVersioningRequest
                {
                    BucketName = bucketName,
                    VersioningConfig = new S3BucketVersioningConfig 
                    {
                        Status = VersionStatus.Enabled
                    }
                };

                PutBucketVersioningResponse response = client.PutBucketVersioning(request);
        }


        static string RetrieveBucketVersioningConfiguration(IAmazonS3 client)
        {
                GetBucketVersioningRequest request = new GetBucketVersioningRequest
                {
                    BucketName = bucketName
                };
 
                GetBucketVersioningResponse response = client.GetBucketVersioning(request);
                return response.VersioningConfig.Status;
            }
    }
}
```

------
#### [ Java ]

有关如何创建和测试有效示例的说明，请参阅《适用于 Java 的 AWS SDK 开发人员指南》中的[入门](https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/getting-started.html)。

```
import java.io.IOException;

import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.regions.Region;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3Client;
import com.amazonaws.services.s3.model.AmazonS3Exception;
import com.amazonaws.services.s3.model.BucketVersioningConfiguration;
import com.amazonaws.services.s3.model.SetBucketVersioningConfigurationRequest;

public class BucketVersioningConfigurationExample {
    public static String bucketName = "*** bucket name ***"; 
    public static AmazonS3Client s3Client;

    public static void main(String[] args) throws IOException {
        s3Client = new AmazonS3Client(new ProfileCredentialsProvider());
        s3Client.setRegion(Region.getRegion(Regions.US_EAST_1));
        try {

            // 1. Enable versioning on the bucket.
        	BucketVersioningConfiguration configuration = 
        			new BucketVersioningConfiguration().withStatus("Enabled");
            
			SetBucketVersioningConfigurationRequest setBucketVersioningConfigurationRequest = 
					new SetBucketVersioningConfigurationRequest(bucketName,configuration);
			
			s3Client.setBucketVersioningConfiguration(setBucketVersioningConfigurationRequest);
			
			// 2. Get bucket versioning configuration information.
			BucketVersioningConfiguration conf = s3Client.getBucketVersioningConfiguration(bucketName);
			 System.out.println("bucket versioning configuration status:    " + conf.getStatus());

        } catch (AmazonS3Exception amazonS3Exception) {
            System.out.format("An Amazon S3 error occurred. Exception: %s", amazonS3Exception.toString());
        } catch (Exception ex) {
            System.out.format("Exception: %s", ex.toString());
        }        
    }
}
```

------
#### [ Python ]

以下 Python 代码示例创建一个 Amazon S3 存储桶，启用它进行版本控制，并配置一个在 7 天后使非当前对象版本过期的生命周期。

```
def create_versioned_bucket(bucket_name, prefix):
    """
    Creates an Amazon S3 bucket, enables it for versioning, and configures a lifecycle
    that expires noncurrent object versions after 7 days.

    Adding a lifecycle configuration to a versioned bucket is a best practice.
    It helps prevent objects in the bucket from accumulating a large number of
    noncurrent versions, which can slow down request performance.

    Usage is shown in the usage_demo_single_object function at the end of this module.

    :param bucket_name: The name of the bucket to create.
    :param prefix: Identifies which objects are automatically expired under the
                   configured lifecycle rules.
    :return: The newly created bucket.
    """
    try:
        bucket = s3.create_bucket(
            Bucket=bucket_name,
            CreateBucketConfiguration={
                "LocationConstraint": s3.meta.client.meta.region_name
            },
        )
        logger.info("Created bucket %s.", bucket.name)
    except ClientError as error:
        if error.response["Error"]["Code"] == "BucketAlreadyOwnedByYou":
            logger.warning("Bucket %s already exists! Using it.", bucket_name)
            bucket = s3.Bucket(bucket_name)
        else:
            logger.exception("Couldn't create bucket %s.", bucket_name)
            raise

    try:
        bucket.Versioning().enable()
        logger.info("Enabled versioning on bucket %s.", bucket.name)
    except ClientError:
        logger.exception("Couldn't enable versioning on bucket %s.", bucket.name)
        raise

    try:
        expiration = 7
        bucket.LifecycleConfiguration().put(
            LifecycleConfiguration={
                "Rules": [
                    {
                        "Status": "Enabled",
                        "Prefix": prefix,
                        "NoncurrentVersionExpiration": {"NoncurrentDays": expiration},
                    }
                ]
            }
        )
        logger.info(
            "Configured lifecycle to expire noncurrent versions after %s days "
            "on bucket %s.",
            expiration,
            bucket.name,
        )
    except ClientError as error:
        logger.warning(
            "Couldn't configure lifecycle on bucket %s because %s. "
            "Continuing anyway.",
            bucket.name,
            error,
        )

    return bucket
```

------

# 配置 MFA 删除
<a name="MultiFactorAuthenticationDelete"></a>

在 Amazon S3 存储桶中使用 S3 版本控制时，您可以选择通过将存储桶配置为启用 *MFA（多重身份验证）删除*来添加另一层安全保护。执行此操作时，存储桶拥有者必须在任何请求中包含两种形式的身份验证，以删除版本或更改存储桶的版本控制状态。

MFA 删除要求对以下任一操作进行额外身份验证：
+ 更改存储桶的版本控制状态
+ 永久删除对象版本

MFA 删除需要结合使用两种形式的身份验证：
+ 您的安全凭证
+ 在已批准的身份验证设备上显示的有效序列号、空格和 6 位代码的组合

MFA 删除因此可在某些情况下（例如在安全凭证被泄露时）提供更高的安全性。MFA 删除要求启动删除操作的用户证明其实际拥有具有 MFA 代码的 MFA 设备，并为删除操作增加额外的摩擦和安全性，从而帮助防止存储桶被意外删除。

要识别已启用了 MFA 删除的存储桶，您可以使用 Amazon S3 Storage Lens 存储统计管理工具指标。S3 Storage Lens 存储统计管理工具是一项云存储分析功能，您可以使用它在整个组织范围内了解对象存储的使用情况和活动。有关更多信息，请参阅[使用 S3 Storage Lens 存储统计管理工具访问存储活动和使用情况](https://docs.aws.amazon.com/AmazonS3/latest/userguide/storage_lens?icmpid=docs_s3_user_guide_MultiFactorAuthenticationDelete.html)。有关指标的完整列表，请参阅 [S3 Storage Lens 存储统计管理工具指标词汇表](https://docs.aws.amazon.com/AmazonS3/latest/userguide/storage_lens_metrics_glossary.html?icmpid=docs_s3_user_guide_MultiFactorAuthenticationDelete.html)。

存储桶拥有者、创建存储存储桶的 AWS 账户（根账户）以及所有授权用户都可以启用版本控制。但是，只有存储桶拥有者（根账户）才能启用 MFA 删除。有关更多信息，请参阅 AWS 安全博客中的[使用 MFA 保护对 AWS 的访问](https://aws.amazon.com/blogs/security/securing-access-to-aws-using-mfa-part-3/)。

**注意**  
要将 MFA 删除与版本控制结合使用，请启用 `MFA Delete`。但是，您无法使用 AWS 管理控制台 启用 `MFA Delete`。您必须使用 AWS Command Line Interface (AWS CLI) 或 API。  
有关将 MFA 删除与版本控制结合使用的示例，请参阅主题 [在存储桶上启用版本控制](manage-versioning-examples.md) 中的示例部分。  
不能将 MFA 删除与生命周期配置一起使用。有关生命周期配置以及如何与其他配置交互的详细信息，请参阅 [S3 生命周期如何与其它存储桶配置进行交互](lifecycle-and-other-bucket-config.md)。

要启用或禁用 MFA 删除，请使用对存储桶配置版本控制时所用的相同 API。Amazon S3 将 MFA 删除配置存储在用于存储桶版本控制状态的相同 *versioning* 子资源中。

```
<VersioningConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/"> 
  <Status>VersioningState</Status>
  <MfaDelete>MfaDeleteState</MfaDelete>  
</VersioningConfiguration>
```

要使用 MFA 删除，您可以使用硬件或虚拟 MFA 设备来生成身份验证代码。以下示例显示了在硬件设备上显示的生成的身份验证代码。

![\[硬件设备上显示的所生成的身份验证代码的示例。\]](http://docs.aws.amazon.com/zh_cn/AmazonS3/latest/userguide/images/MFADevice.png)


MFA 删除和受 MFA 保护的 API 访问的功能旨在提供对不同方案的保护。您可以在存储存储桶上配置 MFA 删除，以协助确保存储桶中的数据不会被意外删除。受 MFA 保护的 API 访问用于在访问敏感的 Amazon S3 资源时，强制执行其他身份验证因素（MFA 代码）。您可以要求使用 MFA 创建的临时证书来完成针对这些 Amazon S3 资源的任何操作。有关示例，请参阅[需要 MFA](example-bucket-policies.md#example-bucket-policies-MFA)。

有关如何购买和激活身份验证设备的更多信息，请参阅[多重身份验证](https://aws.amazon.com/iam/details/mfa/)。

## 启用 S3 版本控制并配置 MFA 删除
<a name="enable-versioning-mfa-delete"></a>

### 使用 AWS CLI
<a name="enable-versioning-mfa-delete-cli"></a>

序列号是唯一标识 MFA 设备的数字。对于物理 MFA 设备，这是设备随附的唯一序列号。对于虚拟 MFA 设备，序列号是设备 ARN。要使用以下命令，请将*用户输入占位符*替换为您自己的信息。

以下示例在存储桶上为物理 MFA 设备启用 S3 版本控制和多重身份验证（MFA）删除。对于物理 MFA 设备，在 `--mfa` 参数中，传递 MFA 设备序列号、空格字符和身份验证设备上显示的值的串联。

```
aws s3api put-bucket-versioning --bucket amzn-s3-demo-bucket1 --versioning-configuration Status=Enabled,MFADelete=Enabled --mfa "SerialNumber 123456"
```

以下示例在存储桶上为虚拟 MFA 设备启用 S3 版本控制和多重身份验证（MFA）删除。对于虚拟 MFA 设备，在 `--mfa` 参数中，传递 MFA 设备 ARN、空格字符和身份验证设备上显示的值的串联。

```
aws s3api put-bucket-versioning --bucket amzn-s3-demo-bucket1 --versioning-configuration Status=Enabled,MFADelete=Enabled --mfa "arn:aws:iam::account-id:mfa/root-account-mfa-device 123789"
```

有关更多信息，请参阅 AWS rePost 文章[如何为我的 Amazon S3 存储桶启用 MFA 删除功能？](https://repost.aws/knowledge-center/s3-bucket-mfa-delete)

### 使用 REST API
<a name="enable-versioning-mfa-delete-rest-api"></a>

有关使用 Amazon S3 REST API 指定 MFA 删除的更多信息，请参阅《Amazon Simple Storage Service API Reference》**中的 [PutBucketVersioning](https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketVersioning.html)。

# 使用启用版本控制的存储桶中的对象
<a name="manage-objects-versioned-bucket"></a>

在您设置版本控制状态之前存储在 Amazon S3 存储桶中的对象的版本 ID 为 `null`。启用版本控制时，存储桶中的现有对象不会更改。更改的是 Amazon S3 在以后的请求中处理这些对象的方式。

**转换对象版本**  
可为具有明确定义的生命周期的对象定义生命周期配置规则，以便在对象生命周期的特定时间将对象版本转换为 S3 Glacier Flexible Retrieval 存储类。有关更多信息，请参阅 [管理对象的生命周期](object-lifecycle-mgmt.md)。

此部分中的主题说明在启用了版本控制的存储桶中进行的各种对象操作。有关版本控制的更多信息，请参阅[使用 S3 版本控制保留对象的多个版本](Versioning.md)。

**Topics**
+ [将对象添加到已启用版本控制的存储桶](AddingObjectstoVersioningEnabledBuckets.md)
+ [列出启用版本控制的存储桶中的对象](list-obj-version-enabled-bucket.md)
+ [从启用了版本控制的存储桶中检索对象版本](RetrievingObjectVersions.md)
+ [从启用了版本控制的存储桶中删除对象版本](DeletingObjectVersions.md)
+ [配置受版本控制的对象权限](VersionedObjectPermissionsandACLs.md)

# 将对象添加到已启用版本控制的存储桶
<a name="AddingObjectstoVersioningEnabledBuckets"></a>

您在存储桶上启用了版本控制后，Amazon S3 会自动将唯一的版本 ID 添加到存储在该存储桶中的每个对象（使用 `PUT`、`POST` 或 `CopyObject`）。

下图显示当将对象添加到已启用版本控制的存储桶时，Amazon S3 会向其添加唯一的版本 ID。

![\[图中显示了在启用了版本控制的存储桶中放置对象时，为该对象添加了唯一版本 ID。\]](http://docs.aws.amazon.com/zh_cn/AmazonS3/latest/userguide/images/versioning_PUT_versionEnabled.png)


**注意**  
Amazon S3 分配的版本 ID 值是 URL 安全的（可以包含在 URI 中）。

有关版本控制的更多信息，请参阅[使用 S3 版本控制保留对象的多个版本](Versioning.md)。您可以使用控制台、AWS SDK 和 REST API 将对象版本添加到启用版本控制的存储桶中。

## 使用 控制台
<a name="add-obj-versioning-enabled-bucket-console"></a>

有关说明，请参阅[上传对象](upload-objects.md)。

## 使用 AWS SDK
<a name="add-obj-versioning-enabled-bucket-sdk"></a>

有关使用适用于 Java、.NET 和 PHP 的 AWS SDK 上传对象的示例，请参阅 [上传对象](upload-objects.md)。在无版本控制和启用版本控制的存储桶中上传对象的示例是相同的，只是对于启用版本控制的存储桶，Amazon S3 会分配版本号。否则，版本号为空。

有关使用其他 AWS SDK 的信息，请参阅 [AWS 开发人员中心](https://aws.amazon.com/code/)。

## 使用 REST API
<a name="add-obj-versioning-enabled-bucket-rest"></a>

**要将对象添加到已启用版本控制的存储桶**

1. 使用 `PutBucketVersioning` 请求在存储桶上启用版本控制。

   有关更多信息，请参阅《Amazon Simple Storage Service API 参考》**中的 [https://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketPUTVersioningStatus.html](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketPUTVersioningStatus.html)。

1. 发送 `PUT`、`POST` 或 `CopyObject` 请求，以在存储桶中存储对象。

当您将对象添加到已启用版本控制的存储桶时，Amazon S3 将在 `x-amz-version-id` 响应标头中返回该对象的版本 ID，如下面的示例所示。

```
1. x-amz-version-id: 3/L4kqtJlcpXroDTDmJ+rmSpXd3dIbrHY
```

# 列出启用版本控制的存储桶中的对象
<a name="list-obj-version-enabled-bucket"></a>

此部分提供从启用版本控制的存储桶列出对象版本的示例。Amazon S3 将对象版本信息存储在与存储桶关联的 *versions* 子资源中。有关更多信息，请参阅 [通用存储桶配置选项](UsingBucket.md#bucket-config-options-intro)。要列出已启用版本控制的存储桶中的对象，您需要 `ListBucketVersions` 权限。

## 使用 S3 控制台
<a name="view-object-versions"></a>

请按照以下步骤使用 Amazon S3 控制台查看对象的不同版本。

**查看对象的多个版本**

1. 登录到 AWS 管理控制台，然后通过以下网址打开 Amazon S3 控制台：[https://console.aws.amazon.com/s3/](https://console.aws.amazon.com/s3/)。

1. 在**存储桶**列表中，请选择包含对象的存储桶的名称。

1. 要查看存储桶中对象的版本列表，请选择**显示版本**开关。

   控制台会显示每个对象版本的唯一版本 ID、对象版本的创建日期和时间以及其他属性。（在您设置版本控制状态之前存储在存储桶中的对象具有版本 ID **null**。）

   要列出没有版本的对象，请选择 **List versions (列出版本)** 开关。

您也可以在控制台中的对象概述面板中查看、下载和删除对象版本。有关更多信息，请参阅 [在 Amazon S3 控制台中查看对象属性](view-object-properties.md)。

**注意**  
 要访问早于 300 个版本的对象版本，必须使用 AWS CLI 或对象的 URL。

**重要**  
仅当对象已作为最新（当前）版本删除时，您才能取消删除它。您无法取消删除已删除对象的早期版本。有关更多信息，请参阅 [使用 S3 版本控制保留对象的多个版本](Versioning.md)。

## 使用 AWS SDK
<a name="list-obj-version-enabled-bucket-sdk-examples"></a>

此部分中的示例说明了如何从启用了版本控制的存储桶中检索对象列表。每个请求最多返回 1000 个版本，除非您指定一个较小的数字。如果存储桶包含的版本数超过此限制，请发送一系列请求来检索所有版本的列表。以“页面”形式返回结果的过程称为*分页*。

为了说明分页的工作原理，该示例将每个响应限制为两个对象版本。在检索第一页结果后，每个示例将检查以确定版本列表是否已被截断。如果是，示例将继续检索页面，直至检索到所有版本。

**注意**  
以下示例还使用未启用版本控制的存储桶或用于没有单独版本的对象。在这些情况下，Amazon S3 将返回版本 ID 为 `null` 的对象列表。

 有关使用其他 AWS SDK 的信息，请参阅 [AWS 开发人员中心](https://aws.amazon.com/code/)。

------
#### [ Java ]

有关创建和测试有效示例的说明，请参阅《适用于 Java 的 AWS SDK 开发人员指南》中的[入门](https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/getting-started.html)。

```
import com.amazonaws.AmazonServiceException;
import com.amazonaws.SdkClientException;
import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.AmazonS3ClientBuilder;
import com.amazonaws.services.s3.model.ListVersionsRequest;
import com.amazonaws.services.s3.model.S3VersionSummary;
import com.amazonaws.services.s3.model.VersionListing;

public class ListKeysVersioningEnabledBucket {

    public static void main(String[] args) {
        Regions clientRegion = Regions.DEFAULT_REGION;
        String bucketName = "*** Bucket name ***";

        try {
            AmazonS3 s3Client = AmazonS3ClientBuilder.standard()
                    .withCredentials(new ProfileCredentialsProvider())
                    .withRegion(clientRegion)
                    .build();

            // Retrieve the list of versions. If the bucket contains more versions
            // than the specified maximum number of results, Amazon S3 returns
            // one page of results per request.
            ListVersionsRequest request = new ListVersionsRequest()
                    .withBucketName(bucketName)
                    .withMaxResults(2);
            VersionListing versionListing = s3Client.listVersions(request);
            int numVersions = 0, numPages = 0;
            while (true) {
                numPages++;
                for (S3VersionSummary objectSummary : versionListing.getVersionSummaries()) {
                    System.out.printf("Retrieved object %s, version %s\n",
                            objectSummary.getKey(),
                            objectSummary.getVersionId());
                    numVersions++;
                }
                // Check whether there are more pages of versions to retrieve. If
                // there are, retrieve them. Otherwise, exit the loop.
                if (versionListing.isTruncated()) {
                    versionListing = s3Client.listNextBatchOfVersions(versionListing);
                } else {
                    break;
                }
            }
            System.out.println(numVersions + " object versions retrieved in " + numPages + " pages");
        } catch (AmazonServiceException e) {
            // The call was transmitted successfully, but Amazon S3 couldn't process
            // it, so it returned an error response.
            e.printStackTrace();
        } catch (SdkClientException e) {
            // Amazon S3 couldn't be contacted for a response, or the client
            // couldn't parse the response from Amazon S3.
            e.printStackTrace();
        }
    }
}
```

------
#### [ .NET ]

有关设置和运行代码示例的信息，请参阅《适用于 .NET 的 AWS SDK 开发人员指南》**中的[适用于 .NET 的 AWS SDK 入门](https://docs.aws.amazon.com/sdk-for-net/latest/developer-guide/net-dg-setup.html)。

```
using Amazon;
using Amazon.S3;
using Amazon.S3.Model;
using System;
using System.Threading.Tasks;

namespace Amazon.DocSamples.S3
{
    class ListObjectsVersioningEnabledBucketTest
    {
        static string bucketName = "*** bucket name ***";
        // Specify your bucket region (an example region is shown).
        private static readonly RegionEndpoint bucketRegion = RegionEndpoint.USWest2;
        private static IAmazonS3 s3Client;

        public static void Main(string[] args)
        {
            s3Client = new AmazonS3Client(bucketRegion);
            GetObjectListWithAllVersionsAsync().Wait();
        }

        static async Task GetObjectListWithAllVersionsAsync()
        {
            try
            {
                ListVersionsRequest request = new ListVersionsRequest()
                {
                    BucketName = bucketName,
                    // You can optionally specify key name prefix in the request
                    // if you want list of object versions of a specific object.

                    // For this example we limit response to return list of 2 versions.
                    MaxKeys = 2
                };
                do
                {
                    ListVersionsResponse response = await s3Client.ListVersionsAsync(request); 
                    // Process response.
                    foreach (S3ObjectVersion entry in response.Versions)
                    {
                        Console.WriteLine("key = {0} size = {1}",
                            entry.Key, entry.Size);
                    }

                    // If response is truncated, set the marker to get the next 
                    // set of keys.
                    if (response.IsTruncated)
                    {
                        request.KeyMarker = response.NextKeyMarker;
                        request.VersionIdMarker = response.NextVersionIdMarker;
                    }
                    else
                    {
                        request = null;
                    }
                } while (request != null);
            }
            catch (AmazonS3Exception e)
            {
                Console.WriteLine("Error encountered on server. Message:'{0}' when writing an object", e.Message);
            }
            catch (Exception e)
            {
                Console.WriteLine("Unknown encountered on server. Message:'{0}' when writing an object", e.Message);
            }
        }
    }
}
```

------

## 使用 REST API
<a name="ListingtheObjectsinaVersioningEnabledBucket"></a>

**Example — 列出存储桶中的所有对象版本**  
要列出存储桶中所有对象的所有版本，请在 `versions` 请求中使用 `GET Bucket` 子资源。Amazon S3 最多能检索 1000 个对象，且每个对象版本都将计为一个完整的对象。因此，如果存储桶包含两个键（例如 `photo.gif` 和 `picture.jpg`），并且第一个键有 990 个版本，第二个键有 400 个版本，则单个请求将检索 `photo.gif` 的所有 990 个版本，另加 `picture.jpg` 的最近 10 个版本。  
Amazon S3 将按照存储的顺序返回对象版本，最先返回最近存储的版本。  
在 `GET Bucket` 请求中，包含 `versions` 子资源。  

```
1. GET /?versions HTTP/1.1
2. Host: bucketName.s3.amazonaws.com
3. Date: Wed, 28 Oct 2009 22:32:00 +0000
4. Authorization: AWS AKIAIOSFODNN7EXAMPLE:0RQf4/cRonhpaBX5sCYVf1bNRuU=
```

**Example — 检索键的所有版本**  
 要检索对象版本的子集，请为 `GET Bucket` 使用请求参数。有关更多信息，请参阅 [https://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketGET.html](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketGET.html)。  

1. 将 `prefix` 参数设置为您要检索的对象的键。

1. 使用 `GET Bucket` 子资源和 `versions` 发送 `prefix` 请求。

   `GET /?versions&prefix=objectName HTTP/1.1`

**Example — 使用前缀检索对象**  
以下示例将检索其键是 `myObject` 或由它开头的对象。  

```
1. GET /?versions&prefix=myObject HTTP/1.1
2. Host: bucket.s3.amazonaws.com
3. Date: Wed, 28 Oct 2009 22:32:00 GMT
4. Authorization: AWS AKIAIOSFODNN7EXAMPLE:0RQf4/cRonhpaBX5sCYVf1bNRuU=
```
您可以使用其他请求参数来检索对象的所有版本的子集。有关更多信息，请参阅《Amazon Simple Storage Service API 参考》**中的 [https://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketGET.html](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketGET.html)。

**Example — 在响应截断时检索其他对象的列表**  
如果可以在 `GET` 请求中返回的对象数量超过 `max-keys` 的值，则响应将包含 `<isTruncated>true</isTruncated>`，并包含满足该请求但不会返回的第一个键 (在 `NextKeyMarker` 中) 和第一个版本 ID (在 `NextVersionIdMarker` 中)。您可以在后续请求中将这些返回的值用作开始位置，以检索满足 `GET` 请求的其他对象。  
使用以下过程从存储桶中检索满足原始 `GET Bucket versions` 请求的其他对象。有关 `key-marker`、`version-id-marker`、`NextKeyMarker` 和 `NextVersionIdMarker` 的更多信息，请参阅《Amazon Simple Storage Service API 参考》**中的 [https://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketGET.html](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketGET.html)。  
以下是满足原始 `GET` 请求的其他响应：  
+ 将 `key-marker` 的值设置为在上一个响应中的 `NextKeyMarker` 中返回的键。
+ 将 `version-id-marker` 的值设置为在上一个响应中的 `NextVersionIdMarker` 中返回的版本 ID。
+ 使用 `GET Bucket versions` 和 `key-marker` 发送 `version-id-marker` 请求。

**Example — 检索以指定的键和版本 ID 开始的对象**  

```
1. GET /?versions&key-marker=myObject&version-id-marker=298459348571 HTTP/1.1
2. Host: bucket.s3.amazonaws.com
3. Date: Wed, 28 Oct 2009 22:32:00 GMT
4. Authorization: AWS AKIAIOSFODNN7EXAMPLE:0RQf4/cRonhpaBX5sCYVf1bNRuU=
```

## 使用 AWS CLI
<a name="list-obj-version-enabled-bucket-cli"></a>

以下命令返回有关存储桶中的对象的所有版本的元数据。

```
aws s3api list-object-versions --bucket amzn-s3-demo-bucket1
```

有关 `list-object-versions` 的更多信息，请参阅《AWS CLI 命令参考》**中的 [https://docs.aws.amazon.com/cli/latest/reference/s3api/list-object-versions.html](https://docs.aws.amazon.com/cli/latest/reference/s3api/list-object-versions.html)。

# 从启用了版本控制的存储桶中检索对象版本
<a name="RetrievingObjectVersions"></a>

Amazon S3 中的版本控制是在相同的存储桶中保留对象的多个变量的方法。简单 `GET` 请求将检索对象的当前版本。下图显示 `GET` 如何返回 `photo.gif` 对象的当前版本。

![\[图中显示了 GET 如何返回对象的当前版本。\]](http://docs.aws.amazon.com/zh_cn/AmazonS3/latest/userguide/images/versioning_GET_NoVersionID.png)


要检索特定版本，您需要指定其版本 ID。下图显示 `GET versionId` 请求检索对象的指定版本 (不一定是当前版本)。

![\[图中显示了 GET versionId 请求如何检索对象的指定版本。\]](http://docs.aws.amazon.com/zh_cn/AmazonS3/latest/userguide/images/versioning_GET_Versioned.png)


您可以使用控制台、AWS SDK 或 REST API 在 Amazon S3 中检索对象版本。

**注意**  
 要访问早于 300 个版本的对象版本，必须使用 AWS CLI 或对象的 URL。

## 使用 S3 控制台
<a name="retrieving-object-versions"></a>

1. 登录到 AWS 管理控制台，然后通过以下网址打开 Amazon S3 控制台：[https://console.aws.amazon.com/s3/](https://console.aws.amazon.com/s3/)。

1. 在**存储桶**列表中，请选择包含对象的存储桶的名称。

1. 在 **Objects**（对象）列表中，请选择对象的名称。

1. 请选择 **Versions**（版本）。

   Amazon S3 显示了对象的所有版本。

1. 选中要检索的版本的 **Version ID**（版本 ID）旁的复选框。

1. 依次选择 **Actions**（操作）、**Download**（下载），然后保存对象。

您也可以在对象概述面板中查看、下载和删除对象版本。有关更多信息，请参阅 [在 Amazon S3 控制台中查看对象属性](view-object-properties.md)。

**重要**  
仅当对象已作为最新 (当前) 版本删除时，您才能取消删除它。您无法取消删除已删除对象的早期版本。有关更多信息，请参阅 [使用 S3 版本控制保留对象的多个版本](Versioning.md)。

## 使用 AWS SDK
<a name="retrieve-obj-version-sdks"></a>

在不受版本控制和启用了版本控制的存储桶中上传对象的示例是相同的。但是，对于启用了版本控制的存储桶，Amazon S3 会分配版本号。否则，版本号为空。

有关使用适用于 Java、.NET 和 PHP 的 AWS SDK 下载对象的示例，请参阅[下载对象](https://docs.aws.amazon.com/AmazonS3/latest/userguide/download-objects.html)。

有关使用适用于 .NET 和 Rust 的 AWS SDK 列出对象版本的示例，请参阅[列出 Amazon S3 存储桶中对象的版本](https://docs.aws.amazon.com/code-library/latest/ug/s3_example_s3_ListObjectVersions_section.html)。

## 使用 REST API
<a name="retrieve-obj-version-rest"></a>

**检索特定对象版本的步骤**

1. 将 `versionId` 设置为您要检索的对象的版本 ID。

1. 发送 `GET Object versionId` 请求。

**Example — 检索受版本控制的对象**  
以下请求将检索 `L4kqtJlcpXroDTDmpUMLUo` 的版本 `my-image.jpg`。  

```
1. GET /my-image.jpg?versionId=L4kqtJlcpXroDTDmpUMLUo HTTP/1.1
2. Host: bucket.s3.amazonaws.com
3. Date: Wed, 28 Oct 2009 22:32:00 GMT
4. Authorization: AWS AKIAIOSFODNN7EXAMPLE:0RQf4/cRonhpaBX5sCYVf1bNRuU=
```

您可以仅检索对象的元数据（而不是内容）。有关信息，请参阅 [检索对象版本的元数据](RetMetaOfObjVersion.md)。

有关还原早期对象版本的信息，请参阅 [还原早期版本](RestoringPreviousVersions.md)。

# 检索对象版本的元数据
<a name="RetMetaOfObjVersion"></a>

如果您仅想检索对象的元数据 (而不是其内容)，您可以使用 `HEAD` 操作。默认情况下，您将获得最新版本的元数据。要检索特定对象版本的元数据，需要指定其版本 ID。

**检索对象版本的元数据的步骤**

1. 将 `versionId` 设置为您要检索其元数据的对象的版本 ID。

1. 发送 `HEAD Object versionId` 请求。

**Example — 检索受版本控制的对象的元数据**  
以下请求将检索 `my-image.jpg` 的版本 `3HL4kqCxf3vjVBH40Nrjfkd` 的元数据。  

```
1. HEAD /my-image.jpg?versionId=3HL4kqCxf3vjVBH40Nrjfkd HTTP/1.1
2. Host: bucket.s3.amazonaws.com
3. Date: Wed, 28 Oct 2009 22:32:00 GMT
4. Authorization: AWS AKIAIOSFODNN7EXAMPLE:0RQf4/cRonhpaBX5sCYVf1bNRuU=
```

以下显示了示例响应。

```
 1. HTTP/1.1 200 OK
 2. x-amz-id-2: ef8yU9AS1ed4OpIszj7UDNEHGran
 3. x-amz-request-id: 318BC8BC143432E5
 4. x-amz-version-id: 3HL4kqtJlcpXroDTDmjVBH40Nrjfkd
 5. Date: Wed, 28 Oct 2009 22:32:00 GMT
 6. Last-Modified: Sun, 1 Jan 2006 12:00:00 GMT
 7. ETag: "fba9dede5f27731c9771645a39863328"
 8. Content-Length: 434234
 9. Content-Type: text/plain
10. Connection: close
11. Server: AmazonS3
```

# 还原早期版本
<a name="RestoringPreviousVersions"></a>

您可以使用版本控制来检索对象的早期版本。有两种方法可执行该操作：
+ 将对象的早期版本复制到同一存储桶中。

  复制的对象将成为该对象的当前版本，且所有对象版本都保留。
+ 永久删除对象的当前版本。

  当您删除当前对象版本时，实际上会将先前版本转换为该对象的当前版本。

由于所有对象版本都保留，所以您可以通过将对象的特定版本复制到同一存储桶，使任何较早版本成为当前版本。在下图中，源对象（ID = 111111）已复制到同一存储桶中。Amazon S3 将提供一个新 ID (88778877)，且它将成为该对象的当前版本。因此，该存储桶同时具有原始对象版本（111111）及其副本（88778877）。有关获取先前版本，然后将其上传以使其成为当前版本的更多信息，请参阅[从启用了版本控制的存储桶中检索对象版本](https://docs.aws.amazon.com/AmazonS3/latest/userguide/RetrievingObjectVersions.html)和[上传对象](https://docs.aws.amazon.com/AmazonS3/latest/userguide/upload-objects.html)。

![\[图中显示了将对象的特定版本复制到同一个存储桶中以使其成为当前版本。\]](http://docs.aws.amazon.com/zh_cn/AmazonS3/latest/userguide/images/versioning_COPY2.png)


随后，`GET` 将检索版本 88778877。

下图显示了如何删除对象的当前版本 (121212)，该操作保留早期版本 (111111) 作为当前版本。有关删除对象的更多信息，请参阅[删除单个对象](https://docs.aws.amazon.com/AmazonS3/latest/userguide/delete-objects.html)。

![\[图中显示了删除对象的当前版本会将早期版本保留为当前版本。\]](http://docs.aws.amazon.com/zh_cn/AmazonS3/latest/userguide/images/versioning_COPY_delete2.png)


随后，`GET` 将检索版本 111111。

**注意**  
要批量还原对象版本，可以[使用 `CopyObject` 操作](https://docs.aws.amazon.com/AmazonS3/latest/userguide/batch-ops-copy-object.html)。`CopyObject` 操作会复制清单中指定的每个对象。但请注意，不必以对象在清单中出现的相同顺序复制这些对象。对于受版本控制的存储桶，如果保留当前/非当前版本顺序很重要，您应首先复制所有非当前版本。然后，在第一个任务完成后，在后续任务中复制当前版本。

## 还原以前的对象版本
<a name="restoring-obj-version-version-enabled-bucket-examples"></a>

有关如何还原已删除对象的更多指导，请参阅 AWS re:Post 知识中心中的[如何检索在启用版本控制的存储桶中删除的 Amazon S3 对象？](https://repost.aws/knowledge-center/s3-undelete-configuration)

### 使用 S3 控制台
<a name="retrieving-object-versions"></a>

1. 登录到 AWS 管理控制台，然后通过以下网址打开 Amazon S3 控制台：[https://console.aws.amazon.com/s3/](https://console.aws.amazon.com/s3/)。

1. 在**存储桶**列表中，请选择包含对象的存储桶的名称。

1. 在 **Objects**（对象）列表中，请选择对象的名称。

1. 请选择 **Versions**（版本）。

   Amazon S3 显示了对象的所有版本。

1. 选中要检索的版本的 **Version ID**（版本 ID）旁的复选框。

1. 依次选择 **Actions**（操作）、**Download**（下载），然后保存对象。

您也可以在对象概述面板中查看、下载和删除对象版本。有关更多信息，请参阅 [在 Amazon S3 控制台中查看对象属性](view-object-properties.md)。

**重要**  
仅当对象已作为最新 (当前) 版本删除时，您才能取消删除它。您无法取消删除已删除对象的早期版本。有关更多信息，请参阅 [使用 S3 版本控制保留对象的多个版本](Versioning.md)。

### 使用 AWS SDK
<a name="restoring-obj-version-version-enabled-bucket-sdks"></a>

有关使用其他 AWS SDK 的信息，请参阅 [AWS 开发人员中心](https://aws.amazon.com/code/)。

------
#### [ Python ]

以下 Python 代码示例通过删除指定回滚版本之后的所有版本，来还原版本控制对象的以前版本。

```
def rollback_object(bucket, object_key, version_id):
    """
    Rolls back an object to an earlier version by deleting all versions that
    occurred after the specified rollback version.

    Usage is shown in the usage_demo_single_object function at the end of this module.

    :param bucket: The bucket that holds the object to roll back.
    :param object_key: The object to roll back.
    :param version_id: The version ID to roll back to.
    """
    # Versions must be sorted by last_modified date because delete markers are
    # at the end of the list even when they are interspersed in time.
    versions = sorted(
        bucket.object_versions.filter(Prefix=object_key),
        key=attrgetter("last_modified"),
        reverse=True,
    )

    logger.debug(
        "Got versions:\n%s",
        "\n".join(
            [
                f"\t{version.version_id}, last modified {version.last_modified}"
                for version in versions
            ]
        ),
    )

    if version_id in [ver.version_id for ver in versions]:
        print(f"Rolling back to version {version_id}")
        for version in versions:
            if version.version_id != version_id:
                version.delete()
                print(f"Deleted version {version.version_id}")
            else:
                break

        print(f"Active version is now {bucket.Object(object_key).version_id}")
    else:
        raise KeyError(
            f"{version_id} was not found in the list of versions for " f"{object_key}."
        )
```

------

# 从启用了版本控制的存储桶中删除对象版本
<a name="DeletingObjectVersions"></a>

您在需要时随时可以从 Amazon S3 存储桶中删除对象版本。您还可为具有明确定义的生命周期的对象定义生命周期配置规则，请求 Amazon S3 使当前对象版本过期，或者永久删除非当前对象版本。当存储桶已启用版本控制或者版本控制已暂停时，生命周期配置操作的工作方式如下：
+ `Expiration` 操作适用于当前对象版本。Amazon S3 通过添加*删除标记*将当前版本作为非当前版本保留（而不是删除当前对象版本），然后删除标记将成为当前版本。
+ `NoncurrentVersionExpiration` 操作适用于非当前对象版本，Amazon S3 会永久删除这些对象版本。无法恢复永久删除的对象。

有关 S3 生命周期的更多信息，请参阅[管理对象的生命周期](object-lifecycle-mgmt.md)和[S3 生命周期配置的示例](lifecycle-configuration-examples.md)。

要查看您的存储桶有多少个当前和非当前对象版本，您可以使用 Amazon S3 Storage Lens 存储统计管理工具指标。S3 Storage Lens 存储统计管理工具是一项云存储分析功能，您可以使用它在整个组织范围内了解对象存储的使用情况和活动。有关更多信息，请参阅[使用 S3 Storage Lens 存储统计管理工具优化存储成本](https://docs.aws.amazon.com/AmazonS3/latest/userguide/storage-lens-optimize-storage.html?icmpid=docs_s3_user_guide_DeletingObjectVersions.html)。有关指标的完整列表，请参阅 [S3 Storage Lens 存储统计管理工具指标词汇表](https://docs.aws.amazon.com/AmazonS3/latest/userguide/storage_lens_metrics_glossary.html?icmpid=docs_s3_user_guide_replication.html)。

**注意**  
 正常的 Amazon S3 费率适用于存储和传输的每个对象版本，包括非当前对象版本。有关更多信息，请参阅 [Amazon S3 定价](https://aws.amazon.com/s3/pricing/)。

## 删除请求使用案例
<a name="delete-request-use-cases"></a>

`DELETE` 请求具有以下使用案例：
+ 启用版本控制后，简单 `DELETE` 无法永久删除对象。（简单 `DELETE` 请求是指未指定版本 ID 的请求。） Amazon S3 将在存储桶中插入删除标记，该删除标记将成为对象的当前版本并具有新的 ID。

  当您尝试对当前版本为删除标记的对象执行 `GET` 操作时，Amazon S3 将该对象作为已删除对象对待（即使它尚未被擦除），并返回 404 错误。有关更多信息，请参阅 [使用删除标记](DeleteMarker.md)。

  下图显示简单 `DELETE` 实际上不会删除指定的对象。但是，Amazon S3 将插入一个删除标记。  
![\[图中显示了删除标记插入。\]](http://docs.aws.amazon.com/zh_cn/AmazonS3/latest/userguide/images/versioning_DELETE_versioningEnabled.png)
+ 要永久删除受版本控制的对象，您必须使用 `DELETE Object versionId`。

  下图显示删除指定的对象版本将永久删除该对象。  
![\[图中显示了 DELETE Object versionId 如何永久删除特定对象版本。\]](http://docs.aws.amazon.com/zh_cn/AmazonS3/latest/userguide/images/versioning_DELETE_versioningEnabled2.png)

## 要删除对象版本
<a name="delete-object-version"></a>

您可以使用控制台、AWS SDK 或 REST API 或 AWS Command Line Interface 删除 Amazon S3 中的对象版本。

### 使用 S3 控制台
<a name="deleting-object-versions"></a>

1. 登录到 AWS 管理控制台，然后通过以下网址打开 Amazon S3 控制台：[https://console.aws.amazon.com/s3/](https://console.aws.amazon.com/s3/)。

1. 在**存储桶**列表中，请选择包含对象的存储桶的名称。

1. 在 **Objects**（对象）列表中，请选择对象的名称。

1. 请选择 **Versions**（版本）。

   Amazon S3 显示了对象的所有版本。

1. 选中要检索的版本的**版本 ID** 旁的复选框。

1. 请选择 **Delete**（删除）。

1. 在 **Permanently delete objects?**（永久删除对象？）中，输入 **permanently delete**。
**警告**  
永久删除对象版本时，该操作将无法撤消。

1. 请选择 **Delete objects**（删除对象）。

   Amazon S3 将删除对象版本。

### 使用 AWS SDK
<a name="delete-obj-version-version-enabled-bucket-sdks"></a>

有关使用适用于 Java、.NET 和 PHP 的 AWS SDK 删除对象的示例，请参阅 [删除 Amazon S3 对象](DeletingObjects.md)。在不受版本控制和启用了版本控制的存储桶中删除对象的示例是相同的。但是，对于启用了版本控制的存储桶，Amazon S3 会分配版本号。否则，版本号为空。

有关使用其他 AWS SDK 的信息，请参阅 [AWS 开发人员中心](https://aws.amazon.com/code/)。

------
#### [ Python ]

以下 Python 代码示例通过删除版本控制对象的所有版本永久删除了该对象。

```
def permanently_delete_object(bucket, object_key):
    """
    Permanently deletes a versioned object by deleting all of its versions.

    Usage is shown in the usage_demo_single_object function at the end of this module.

    :param bucket: The bucket that contains the object.
    :param object_key: The object to delete.
    """
    try:
        bucket.object_versions.filter(Prefix=object_key).delete()
        logger.info("Permanently deleted all versions of object %s.", object_key)
    except ClientError:
        logger.exception("Couldn't delete all versions of %s.", object_key)
        raise
```

------

### 使用 REST API
<a name="delete-obj-version-enabled-bucket-rest"></a>

**删除对象的特定版本**
+ 在 `DELETE` 中，指定版本 ID。

**Example — 删除特定版本**  
以下示例删除了 `UIORUnfnd89493jJFJ` 的版本 `photo.gif`。  

```
1. DELETE /photo.gif?versionId=UIORUnfnd89493jJFJ HTTP/1.1 
2. Host: bucket.s3.amazonaws.com
3. Date: Wed, 12 Oct 2009 17:50:00 GMT
4. Authorization: AWS AKIAIOSFODNN7EXAMPLE:xQE0diMbLRepdf3YB+FIEXAMPLE=
5. Content-Type: text/plain
6. Content-Length: 0
```

### 使用 AWS CLI
<a name="delete-obj-version-enabled-bucket-cli"></a>

以下命令从名为 `amzn-s3-demo-bucket1` 的存储桶中删除名为 test.txt 的对象。要删除特定版本的对象，您必须是存储桶拥有者，并且您必须使用版本 Id 子资源。

```
aws s3api delete-object --bucket amzn-s3-demo-bucket1 --key test.txt --version-id versionID
```

有关 `delete-object` 的更多信息，请参阅《AWS CLI 命令参考》**中的 [https://docs.aws.amazon.com/cli/latest/reference/s3api/delete-object.html](https://docs.aws.amazon.com/cli/latest/reference/s3api/delete-object.html)。

有关删除对象版本的更多信息，请参阅以下主题：
+ [使用删除标记](DeleteMarker.md)
+ [删除删除标记以使旧版本变为当前版本](ManagingDelMarkers.md#RemDelMarker)
+ [从启用了 MFA 删除的存储桶中删除对象](UsingMFADelete.md)

# 使用删除标记
<a name="DeleteMarker"></a>

Amazon S3 中的*删除标记*是用于在简单 `DELETE` 请求中指定的、启用了版本控制的对象的占位符（或标记）。简单 `DELETE` 请求是指未指定版本 ID 的请求。因为对象位于已启用版本控制的存储桶中，所以不能删除该对象。但是，删除标记可以使 Amazon S3 的行为类似于对象已被删除。在删除标记上可以使用 Amazon S3 API `DELETE` 调用。为此，您必须使用具有适当权限的 AWS Identity and Access Management (IAM) 用户或角色来发出 `DELETE` 请求。

与任何其他对象一样，删除标记同样有*键名*（或*键*）和版本 ID。但是，删除标记在以下方面与其他对象不同：
+ 删除标记没有与之关联的数据。
+ 删除标记不与访问控制列表 (ACL) 值关联。
+ 如果您针对删除标记发出 `GET` 请求，则 `GET` 请求不会检索任何内容，因为删除标记没有数据。具体而言，如果您的 `GET` 请求未指定 `versionId`，则会收到 404（未找到）错误。

删除标记会对 Amazon S3 中的存储产生极少的费用。删除标记的存储大小等于删除标记键名的大小。键名是 Unicode 字符序列。对于名称中的每个字符，键名的 UTF-8 编码将 1 到 4 字节的存储添加到存储桶中。删除标记存储在 S3 Standard 存储类中。

如果您想知道自己有多少个删除标记以及它们存储在哪个存储类中，可以使用 Amazon S3 Storage Lens 存储统计管理工具。有关更多信息，请参阅[使用 Amazon S3 Storage Lens 存储统计管理工具监控您的存储活动和使用情况](storage_lens.md)和[Amazon S3 Storage Lens 存储统计管理工具指标词汇表](storage_lens_metrics_glossary.md)。

有关键名称的更多信息，请参阅 [为 Amazon S3 对象命名](object-keys.md)。有关将删除标记删除的信息，请参阅 [管理删除标记](ManagingDelMarkers.md)。

仅 Amazon S3 可以创建删除标记，且当您在已启用版本控制或已暂停版本控制的存储桶的对象上发送 `DeleteObject` 请求时执行此操作。在 `DELETE` 请求中指定的对象不会实际删除。而是使删除标记成为对象的当前版本。该对象的键名（键）将成为删除标记的键。

如果您获取对象而未在请求中指定 `versionId`，如果其当前版本是一个删除标记，则 Amazon S3 的响应如下：
+ 404（未找到）错误
+ 响应标头，`x-amz-delete-marker: true`

当您通过在请求中指定 `versionId` 来获取对象时，如果其当前版本是一个删除标记，则 Amazon S3 的响应如下：
+ 405（不允许此方法）错误
+ 响应标头，`x-amz-delete-marker: true`
+ 响应标头，`Last-Modified: timestamp`（仅在使用 [HeadObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_HeadObject.html) 或 [GetObject](https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetObject.html) API 操作时）

`x-amz-delete-marker: true` 响应标头告知您所访问的对象是删除标记。此响应标头永远不会返回 `false`，因为当值为时 `false`，对象的当前版本或指定版本不是删除标记。

`Last-Modified` 响应标头提供删除标记的创建时间。

下图显示了对当前版本为删除标记的对象进行 `GetObject` API 调用时，该调用如何使用 404（未找到）错误进行响应且响应标头中包括 `x-amz-delete-marker: true`。

![\[图中显示了对删除标记的 GetObject 调用返回 404（未找到）错误。\]](http://docs.aws.amazon.com/zh_cn/AmazonS3/latest/userguide/images/versioning_DELETE_NoObjectFound.png)


如果您通过在请求中指定 `versionId` 来对对象进行 `GetObject` 调用，并且指定的版本是删除标记，则 Amazon S3 会以 405（不允许方法）错误进行响应，且响应标头包括 `x-amz-delete-marker: true` 和 `Last-Modified: timestamp`。

![\[图中显示了对删除标记的 GetObject 调用返回 405（不允许此方法）错误。\]](http://docs.aws.amazon.com/zh_cn/AmazonS3/latest/userguide/images/versioning_DELETE_NoObjectFound_405.png)


即使被覆盖，删除标记也仍保留在对象版本中。列出删除标记（和对象的其它版本）的唯一方法是使用 [https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjectVersions.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjectVersions.html) 请求。可以在 AWS 管理控制台中通过列出通用存储桶中的对象并选择**显示版本**来提出此请求。有关更多信息，请参阅 [列出启用版本控制的存储桶中的对象](list-obj-version-enabled-bucket.md)。

下图显示 [https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjectsV2.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjectsV2.html) 或 [https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjects.html](https://docs.aws.amazon.com/AmazonS3/latest/API/API_ListObjects.html) 请求不会返回其当前版本为删除标记的对象。

![\[图中显示了 ListObjectsV2 或 ListObjects 调用如何不返回任何删除标记。\]](http://docs.aws.amazon.com/zh_cn/AmazonS3/latest/userguide/images/versioning_GETBucketwithDeleteMarkers.png)


# 管理删除标记
<a name="ManagingDelMarkers"></a>

## 配置生命周期以自动清理过期的删除标记
<a name="LifecycleDelMarker"></a>

过期的对象删除标记是指，删除所有对象版本而只保留一个删除标记。如果生命周期配置设置为删除当前版本，或显式设置了 `ExpiredObjectDeleteMarker` 操作，则 Amazon S3 会删除过期对象的删除标记。有关示例，请参阅[在启用了版本控制的存储桶中移除到期对象删除标记](lifecycle-configuration-examples.md#lifecycle-config-conceptual-ex7)。

## 删除删除标记以使旧版本变为当前版本
<a name="RemDelMarker"></a>

当您删除启用了版本控制的存储桶中的某个对象时，所有版本都将保留在存储桶中并且 Amazon S3 将为该对象创建一个删除标记。要取消删除该对象，您必须删除此删除标记。有关版本控制和删除标记的更多信息，请参阅[使用 S3 版本控制保留对象的多个版本](Versioning.md)。

要永久删除“删除标记”，必须在 `DeleteObject versionId` 请求中包含其版本 ID。下图显示了 `DeleteObject versionId` 请求如何永久删除“删除标记”。

![\[图中显示了使用其版本 ID 的删除标记删除。\]](http://docs.aws.amazon.com/zh_cn/AmazonS3/latest/userguide/images/versioning_DELETE_deleteMarkerVersioned.png)


去除删除标记的效果是：简单的 `GET` 请求现在将检索对象的当前版本 ID（121212）。

**注意**  
如果在当前版本是一个删除标记（未指定删除标记的版本 ID）的情况下使用 `DeleteObject` 请求，Amazon S3 将不会删除该删除标记，而是对另一个删除标记执行 `PUTs` 请求。

要删除具有 `NULL` 版本 ID 的删除标记，必须在 `DeleteObject` 请求中将 `NULL` 作为版本 ID 传递。下图显示了在没有版本 ID（当前版本是一个删除标记）的情况下如何发出简单的 `DeleteObject` 请求，未删除任何内容，而是再添加一个具有唯一版本 ID (7498372) 的删除标记。

![\[图中显示了使用 NULL 版本 ID 的删除标记删除。\]](http://docs.aws.amazon.com/zh_cn/AmazonS3/latest/userguide/images/versioning_DELETE_deleteMarker.png)


## 使用 S3 控制台
<a name="undelete-objects"></a>

按照以下步骤，从 S3 存储桶中恢复文件夹之外的已删除对象，包括这些文件夹中的对象。

1. 登录到 AWS 管理控制台，然后通过以下网址打开 Amazon S3 控制台：[https://console.aws.amazon.com/s3/](https://console.aws.amazon.com/s3/)。

1. 在**存储桶**列表中，请选择您想要的存储桶的名称。

1. 要查看存储桶中对象的**版本**列表，请选择**列出版本**开关。您将能够看到已删除对象的删除标记。

   

1. 要取消删除对象，您必须删除掉删除标记。选中要恢复的对象的**删除标记**旁边的复选框，然后选择 **Delete (删除)**。

1. 在 **Delete objects (删除对象)** 页面上确认删除。

   1. 对于 **Permanently delete objects?**（永久删除对象？），输入 **permanently delete**。

   1. 请选择 **Delete objects**（删除对象）。

**注意**  
您无法使用 Amazon S3 控制台取消删除文件夹。您必须使用 AWS CLI 或 SDK。例如，请参阅 AWS 知识中心中的[如何检索启用版本控制的存储桶中已被删除的 Amazon S3 对象？](https://aws.amazon.com/premiumsupport/knowledge-center/s3-undelete-configuration/)。

## 使用 REST API
<a name="delete-marker-rest-api"></a>

**永久删除“删除标记”的步骤**

1. 将 `versionId` 设置为要删除的删除标记的版本 ID。

1. 发送 `DELETE Object versionId` 请求。

**Example — 删除“删除标记”**  
以下示例删除用于 `photo.gif` 版本 4857693 的删除标记。  

```
1. DELETE /photo.gif?versionId=4857693 HTTP/1.1
2. Host: bucket.s3.amazonaws.com
3. Date: Wed, 28 Oct 2009 22:32:00 GMT
4. Authorization: AWS AKIAIOSFODNN7EXAMPLE:0RQf4/cRonhpaBX5sCYVf1bNRuU=
```

删除“删除标记”时，Amazon S3 将在响应中包含以下内容：

```
1. 204 NoContent 
2. x-amz-version-id: versionID 
3. x-amz-delete-marker: true
```

## 使用 AWS SDK
<a name="remove-delete-marker-examples-sdk"></a>

有关使用其他 AWS SDK 的信息，请参阅 [AWS 开发人员中心](https://aws.amazon.com/code/)。

------
#### [ Python ]

以下 Python 代码示例演示了如何从对象中删除“删除标记”，从而使最新的非当前版本成为对象的当前版本。

```
def revive_object(bucket, object_key):
    """
    Revives a versioned object that was deleted by removing the object's active
    delete marker.
    A versioned object presents as deleted when its latest version is a delete marker.
    By removing the delete marker, we make the previous version the latest version
    and the object then presents as *not* deleted.

    Usage is shown in the usage_demo_single_object function at the end of this module.

    :param bucket: The bucket that contains the object.
    :param object_key: The object to revive.
    """
    # Get the latest version for the object.
    response = s3.meta.client.list_object_versions(
        Bucket=bucket.name, Prefix=object_key, MaxKeys=1
    )

    if "DeleteMarkers" in response:
        latest_version = response["DeleteMarkers"][0]
        if latest_version["IsLatest"]:
            logger.info(
                "Object %s was indeed deleted on %s. Let's revive it.",
                object_key,
                latest_version["LastModified"],
            )
            obj = bucket.Object(object_key)
            obj.Version(latest_version["VersionId"]).delete()
            logger.info(
                "Revived %s, active version is now %s  with body '%s'",
                object_key,
                obj.version_id,
                obj.get()["Body"].read(),
            )
        else:
            logger.warning(
                "Delete marker is not the latest version for %s!", object_key
            )
    elif "Versions" in response:
        logger.warning("Got an active version for %s, nothing to do.", object_key)
    else:
        logger.error("Couldn't get any version info for %s.", object_key)
```

------

# 从启用了 MFA 删除的存储桶中删除对象
<a name="UsingMFADelete"></a>

在配置 MFA 删除时，只有根用户才能永久删除对象版本或更改 S3 存储桶上的版本控制配置。您必须使用 MFA 设备对根用户进行身份验证，才能执行删除操作。

如果存储桶的版本控制配置已启用 MFA 删除，则存储桶拥有者必须在请求中包含 `x-amz-mfa` 请求标头，才能永久删除对象版本或更改该存储存储桶的版本控制状态。包含 `x-amz-mfa` 的请求必须使用 HTTPS。

标头的值由身份验证设备的序列号、空格，以及在该设备上显示的身份验证代码组成。如果您没有包含此请求标头，则请求失败。

使用 AWS CLI 时，请包含与 `mfa` 参数的值相同的信息。

有关身份验证设备的更多信息，请参阅[多重身份验证](https://aws.amazon.com/iam/details/mfa/)。

有关启用 MFA 删除的更多信息，请参阅 [配置 MFA 删除](MultiFactorAuthenticationDelete.md)。

**注意**  
在启用了 MFA 删除且启用版本控制的存储桶中删除对象无法通过 AWS 管理控制台来实现。

## 使用 AWS CLI
<a name="MFADeleteCLI"></a>

要在启用了 MFA 删除且启用版本控制的存储桶中删除对象，请使用以下命令。当您使用以下示例命令时，请将 `user input placeholders` 替换为您自己的信息。

```
 aws s3api delete-object --bucket amzn-s3-demo-bucket --key OBJECT-KEY --version-id "VERSION ID" --mfa "MFA_DEVICE_SERIAL_NUMBER MFA_DEVICE_CODE"						
```

## 使用 REST API
<a name="MFADeleteAPI"></a>

以下示例删除了在存储桶中配置为启用 MFA 删除的 `my-image.jpg`（具有指定版本）。

有关更多信息，请参阅《Amazon Simple Storage Service API Reference》中的 [https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectDELETE.html](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectDELETE.html)。

```
1. DELETE /my-image.jpg?versionId=3HL4kqCxf3vjVBH40Nrjfkd HTTPS/1.1
2. Host: bucketName.s3.amazonaws.com
3. x-amz-mfa: 20899872 301749
4. Date: Wed, 28 Oct 2009 22:32:00 GMT
5. Authorization: AWS AKIAIOSFODNN7EXAMPLE:0RQf4/cRonhpaBX5sCYVf1bNRuU=
```

# 配置受版本控制的对象权限
<a name="VersionedObjectPermissionsandACLs"></a>

Amazon S3 中的对象的权限在版本级别设置。每个版本都有自己的对象拥有者。创建对象版本的 AWS 账户 是拥有者。因此，您可以为同一对象的不同版本设置不同的权限。要这样做，您必须指定要在 `PUT Object versionId acl` 请求中设置其权限的对象的版本 ID。有关详细描述和关于使用 ACL 的说明，请参阅 [Amazon S3 的身份和访问管理](security-iam.md)。

**Example — 为对象版本设置权限**  
以下请求针对具有规范用户 ID *b4bf1b36f9716f094c3079dcf5ac9982d4f2847de46204d47448bc557fb5ac2a* 的被授权者，将其对键 `my-image.jpg`（版本 ID 为 `3HL4kqtJvjVBH40Nrjfkd`）的权限设置为 `FULL_CONTROL`。  

```
 1. PUT /my-image.jpg?acl&versionId=3HL4kqtJvjVBH40Nrjfkd HTTP/1.1
 2. Host: bucket.s3.amazonaws.com
 3. Date: Wed, 28 Oct 2009 22:32:00 GMT
 4. Authorization: AWS AKIAIOSFODNN7EXAMPLE:0RQf4/cRonhpaBX5sCYVf1bNRuU=
 5. Content-Length: 124
 6.  
 7. <AccessControlPolicy>
 8.   <Owner>
 9.     <ID>75cc57f09aa0c8caeab4f8c24e99d10f8e7faeebf76c078efc7c6caea54ba06a</ID>
10.   </Owner>
11.   <AccessControlList>
12.     <Grant>
13.       <Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CanonicalUser">
14.         <ID>a9a7b886d6fd24a52fe8ca5bef65f89a64e0193f23000e241bf9b1c61be666e9</ID>
15.       </Grantee>
16.       <Permission>FULL_CONTROL</Permission>
17.     </Grant>
18.   </AccessControlList>
19.   </AccessControlPolicy>
```

同样地，要获取特定对象版本的权限，必须在 `GET Object versionId acl` 请求中指定它的版本 ID。您需要包含版本 ID，因为在默认情况下，`GET Object acl` 将返回对象的当前版本的权限。

**Example — 检索用于指定对象版本的权限**  
在以下示例中，Amazon S3 将返回对于键（`my-image.jpg`）和版本 ID（`DVBH40Nr8X8gUMLUo`）的权限。  

```
1. GET /my-image.jpg?versionId=DVBH40Nr8X8gUMLUo&acl HTTP/1.1
2. Host: bucket.s3.amazonaws.com
3. Date: Wed, 28 Oct 2009 22:32:00 GMT
4. Authorization: AWS AKIAIOSFODNN7EXAMPLE:0RQf4/cRonhpaBX5sCYVf1bNRuU
```

有关更多信息，请参阅《Amazon Simple Storage Service API 参考》**中的 [https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectGETacl.html](https://docs.aws.amazon.com/AmazonS3/latest/API/RESTObjectGETacl.html)。

# 使用已暂停版本控制的存储桶中的对象
<a name="VersionSuspendedBehavior"></a>

在 Amazon S3 中，您可以暂停版本控制，以停止在存储桶中累积同一对象的新版本。您可能这样做是因为您只想在存储桶中使用单个版本的对象。或者，您可能不想为多个版本累积费用。

暂停版本控制时，存储桶中的现有对象不会更改。更改的是 Amazon S3 在以后的请求中处理对象的方式。本部分中的主题介绍了暂停版本控制的存储桶中的各种对象操作，包括添加、检索和删除对象。

有关 S3 版本控制的更多信息，请参阅[使用 S3 版本控制保留对象的多个版本](Versioning.md)。有关检索对象版本的更多信息，请参阅 [从启用了版本控制的存储桶中检索对象版本](RetrievingObjectVersions.md)。

**Topics**
+ [将对象添加到已暂停版本控制的存储桶](AddingObjectstoVersionSuspendedBuckets.md)
+ [从已暂停版本控制的存储桶检索对象](RetrievingObjectsfromVersioningSuspendedBuckets.md)
+ [从已暂停版本控制的存储桶中删除对象](DeletingObjectsfromVersioningSuspendedBuckets.md)

# 将对象添加到已暂停版本控制的存储桶
<a name="AddingObjectstoVersionSuspendedBuckets"></a>

您可以将对象添加到 Amazon S3 中已暂停版本控制的存储桶中，以便创建具有空版本 ID 的对象，或者覆盖具有匹配版本 ID 的任何对象版本。

您在存储桶上暂停了版本控制后，Amazon S3 会自动将 `null` 版本 ID 添加到之后存储在该存储段中的每个后续对象（使用 `PUT`、`POST` 或 `CopyObject`）。

下图显示了当将对象添加到暂停版本控制的存储桶时，Amazon S3 将如何向该对象添加 `null` 的版本 ID。

![\[Amazon S3 在对象图形中添加的版本 ID 为 null。\]](http://docs.aws.amazon.com/zh_cn/AmazonS3/latest/userguide/images/versioning_PUT_versionSuspended.png)


如果存储桶中已存在空版本，且您使用同一键添加了其他对象，则添加的对象将覆盖原始的空版本。

如果存储桶中存在受版本控制的对象，则使用 `PUT` 存储的版本将成为该对象的当前版本。下图显示了如何将对象添加到包含受版本控制的对象（不会覆盖已存在于该存储桶中的对象）的存储桶。

在这种情况下，版本 111111 已存在于该存储桶中。Amazon S3 会将空的版本 ID 附加到所添加的对象，并将其存储在存储桶中。版本 111111 不会被覆盖。

![\[Amazon S3 在不覆盖版本 111111 图形的情况下向对象添加的版本 ID 为 null。\]](http://docs.aws.amazon.com/zh_cn/AmazonS3/latest/userguide/images/versioning_PUT_versionSuspended3.png)


如果存储桶中已存在空版本，则该空版本将被覆盖，如下图所示。

![\[Amazon S3 在覆盖原始内容图形的同时向对象添加的版本 ID 为 null。\]](http://docs.aws.amazon.com/zh_cn/AmazonS3/latest/userguide/images/versioning_PUT_versionSuspended4.png)


虽然空版本的键和版本 ID（`null`）在 `PUT` 之前和之后都相同，但是原来存储在存储桶中的空版本的内容将替换为该存储桶中对象 `PUT` 的内容。

# 从已暂停版本控制的存储桶检索对象
<a name="RetrievingObjectsfromVersioningSuspendedBuckets"></a>

无论是否在存储桶上启用版本控制，`GET Object` 请求都将返回对象的当前版本。下图显示了简单 `GET` 将如何返回对象的当前版本。

![\[图中显示了简单 GET 如何返回对象的当前版本。\]](http://docs.aws.amazon.com/zh_cn/AmazonS3/latest/userguide/images/versioning_GET_suspended.png)


# 从已暂停版本控制的存储桶中删除对象
<a name="DeletingObjectsfromVersioningSuspendedBuckets"></a>

您可以将对象从暂停版本控制的存储桶中删除，以便删除具有空版本 ID 的对象。

如果某个存储桶的版本控制已暂停，`DELETE` 请求：
+ 可以仅删除其版本 ID 为 `null` 的对象。
+ 如果存储桶中没有对象的空版本，则不删除任何内容。
+ 将删除标记插入到存储桶。

如果暂停存储桶版本控制，该操作会移除具有空 `versionId` 的对象。如果版本 ID 存在，Amazon S3 会插入删除标记，该删除标记将成为对象的当前版本。下图显示了简单的 `DELETE` 移除空版本和 Amazon S3 改而使用 `null` 版本 ID 在其位置中插入删除标记的方式。

![\[图中显示了简单删除，用于移除版本 ID 为 NULL 的对象。\]](http://docs.aws.amazon.com/zh_cn/AmazonS3/latest/userguide/images/versioning_DELETE_versioningSuspended.png)


要永久删除具有 `versionId` 的对象，必须在请求中包含对象的 `versionId`。由于删除标记不包含任何内容，因此，您将在删除标记替换 `null` 版本时丢失该版本的内容。

下图显示不具有空版本的存储桶。在这种情况下，`DELETE` 不会移除任何内容。而是 Amazon S3 仅仅插入一个删除标记。

![\[图中显示了删除标记插入。\]](http://docs.aws.amazon.com/zh_cn/AmazonS3/latest/userguide/images/versioning_DELETE_versioningSuspendedNoNull.png)


即使是在已暂停版本控制的存储桶中，存储桶拥有者也可以通过在 `DELETE` 请求中包括版本 ID 来永久删除指定的版本，除非已明确拒绝 `DELETE` 请求的权限。例如，要拒绝删除具有版本 ID `null` 的任何对象，您必须明确拒绝 `s3:DeleteObject` 和 `s3:DeleteObjectVersions` 权限。

下图显示删除指定的对象版本将永久删除该版本的对象。只有存储桶拥有者可以删除指定的对象版本。

![\[图中显示了使用指定版本 ID 永久删除对象。\]](http://docs.aws.amazon.com/zh_cn/AmazonS3/latest/userguide/images/versioning_DELETE_versioningEnabled2.png)


# 版本控制故障排除
<a name="troubleshooting-versioning"></a>

以下主题可以帮助您排查一些常见的 Amazon S3 版本控制问题。

**Topics**
+ [我想恢复在启用版本控制的存储桶中意外删除的对象](#recover-objects)
+ [我想永久删除受版本控制的对象](#delete-objects-permanent)
+ [启用存储桶版本控制后，我遇到了性能下降问题](#performance-degradation)

## 我想恢复在启用版本控制的存储桶中意外删除的对象
<a name="recover-objects"></a>

通常，当从 S3 存储桶中删除对象版本时，Amazon S3 无法恢复它们。但是，如果您在 S3 存储桶上启用了 S3 版本控制，则未指定版本 ID 的 `DELETE` 请求无法永久删除对象。而是添加删除标记作为占位符。此删除标记将成为对象的当前版本。

要验证已删除的对象是永久删除还是临时删除（在其所在位置有删除标记），请执行以下操作：

1. 登录到 AWS 管理控制台，然后通过以下网址打开 Amazon S3 控制台：[https://console.aws.amazon.com/s3/](https://console.aws.amazon.com/s3/)。

1. 在左侧导航窗格中，选择**存储桶**。

1. 在**存储桶**列表中，请选择包含对象的存储桶的名称。

1. 在**对象**列表中，开启搜索栏右侧的**显示版本**开关，然后在搜索栏中搜索已删除的对象。仅当之前在存储桶上启用了版本控制时，此开关才可用。

   您也可以使用 [S3 清单来搜索已删除的对象](storage-inventory.md#storage-inventory-contents)。

1. 如果在切换**显示版本**或创建清单报告后找不到对象，也找不到该对象的[删除标记](DeleteMarker.md)，则删除是永久性的，无法恢复该对象。



您还可以使用 AWS Command Line Interface（AWS CLI）中的 `HeadObject` API 操作来验证已删除对象的状态。要执行此操作，请使用以下 `head-object` 命令并将 `user input placeholders` 替换为您自己的信息：

`aws s3api head-object --bucket amzn-s3-demo-bucket --key index.html`

如果您对受版本控制的对象运行 `head-object` 命令，而此对象的当前版本为删除标记，则会收到 404 找不到错误。例如：

调用 HeadObject 操作时发生错误（404）：找不到

如果您对受版本控制的对象运行 `head-object` 命令并提供该对象的版本 ID，Amazon S3 将检索该对象的元数据，确认该对象仍然存在而未被永久删除。

`aws s3api head-object --bucket amzn-s3-demo-bucket --key index.html --version-id versionID`

```
{
"AcceptRanges": "bytes",
"ContentType": "text/html",
"LastModified": "Thu, 16 Apr 2015 18:19:14 GMT",
"ContentLength": 77,
"VersionId": "Zg5HyL7m.eZU9iM7AVlJkrqAiE.0UG4q",
"ETag": "\"30a6ec7e1a9ad79c203d05a589c8b400\"",
"Metadata": {}
}
```

如果找到该对象并且最新版本是删除标记，则该对象的先前版本仍然存在。由于删除标记是对象的当前版本，因此您可以通过删除该删除标记来恢复对象。

永久移除删除标记后，该对象的第二个最新版本将成为该对象的当前版本，从而使您的对象再次可用。有关如何恢复对象的直观描述，请参阅[移除删除标记](ManagingDelMarkers.md#RemDelMarker)。

要删除对象的特定版本，您必须是存储桶拥有者。要永久删除“删除标记”，必须在 `DeleteObject` 请求中包含其版本 ID。要删除该删除标记，请使用以下命令，然后将 `user input placeholders` 替换为您自己的信息：

****  
`aws s3api delete-object --bucket amzn-s3-demo-bucket --key index.html --version-id versionID`

有关 `delete-object` 命令的更多信息，请参阅《AWS CLI 命令参考》**中的 [https://docs.aws.amazon.com//cli/latest/reference/s3api/delete-object.html](https://docs.aws.amazon.com//cli/latest/reference/s3api/delete-object.html)。有关永久删除相应删除标记的更多信息，请参阅[管理删除标记](ManagingDelMarkers.md)。

## 我想永久删除受版本控制的对象
<a name="delete-objects-permanent"></a>

在已启用版本控制的存储桶中，没有版本 ID 的 `DELETE` 请求无法永久删除对象。相反，此类请求会插入一个删除标记。

要永久删除受版本控制的对象，可从以下方法中进行选择：
+ 创建 S3 生命周期规则以永久删除非当前版本。要永久删除非当前版本，请选择**永久删除对象的非当前版本**，然后在**对象变为非当前对象后的天数**下输入一个数字。您可以选择在 **Number of newer versions to retain**（要保留的较新版本的数量）下输入一个值，从而指定要保留的较新版本数量。有关创建此规则的更多信息，请参阅[设置 S3 生命周期配置](how-to-set-lifecycle-configuration-intro.md)。
+ 通过在 `DELETE` 请求中包含版本 ID 来删除指定的版本。有关更多信息，请参阅[如何永久删除受版本控制的对象](DeletingObjectVersions.md#delete-request-use-cases)。
+ 创建生命周期规则以使当前版本过期。要使对象的当前版本过期，请选择**将对象的当前版本设为过期**，然后在**创建对象后的天数**下输入一个数字。有关创建此生命周期规则的更多信息，请参阅[设置 S3 生命周期配置](how-to-set-lifecycle-configuration-intro.md)。
+ 要永久删除所有受版本控制的对象以及删除标记，请创建两个生命周期规则：一个用于使当前版本过期并永久删除对象的非当前版本，另一个用于删除过期的对象删除标记。

在启用版本控制的存储桶中，未指定版本 ID 的 `DELETE` 请求只能删除具有 `NULL` 版本 ID 的对象。如果对象是在启用版本控制后上传的，则未指定版本 ID 的 `DELETE` 请求会创建该对象的删除标记。

**注意**  
对于启用了 S3 对象锁定的存储桶，具有受保护对象版本 ID 的 `DELETE` 对象请求会导致 403 拒绝访问错误。没有版本 ID 的 `DELETE` 对象请求会添加删除标记作为该对象的最新版本，响应为 200 OK。受对象锁定保护的对象只有在解除其保留期和法定保留之后才可永久删除。有关更多信息，请参阅 [S3 对象锁定的工作原理](object-lock.md#object-lock-overview)。

## 启用存储桶版本控制后，我遇到了性能下降问题
<a name="performance-degradation"></a>

如果删除标记或受版本控制的对象过多，以及如果未遵循最佳实践，则启用版本控制的存储桶可能会出现性能降低问题。

**删除标记过多**  
对存储桶启用版本控制后，针对对象发出的没有版本 ID 的 `DELETE` 请求将创建具有唯一版本 ID 的删除标记。具有**将对象的当前版本设为过期**规则的生命周期配置会向每个对象添加一个带有唯一版本 ID 的删除标记。过多的删除标记会降低存储桶的性能。

在对存储桶暂停版本控制时，Amazon S3 会对于新创建的对象将版本 ID 标记为 `NULL`。版本控制已暂停的存储桶中的过期操作会导致 Amazon S3 创建一个以 `NULL` 作为版本 ID 的删除标记。在版本控制已暂停的存储桶中，将为任何删除请求创建 `NULL` 删除标记。当删除所有对象版本而只保留单个删除标记时，这些 `NULL` 删除标记也称为过期对象删除标记。如果累积的 `NULL` 删除标记过多，则存储桶的性能会降低。

**受版本控制的对象过多**  
如果启用了版本控制的存储桶包含具有数百万个版本的对象，则可能会出现 503 服务不可用错误。如果您注意到针对启用版本控制的存储存储桶的 `PUT` 或 `DELETE` 对象请求接收的 HTTP 503 服务不可用响应的数量显著增加，则存储桶中可能有一个或多个对象具有数百万个版本。如果您的对象有数以百万计的版本，Amazon S3 会自动限制对该存储桶的请求。限制请求数可以保护您的存储桶免受过多请求流量的影响，但也可能会妨碍对该存储桶发出的其他请求。

要确定哪些对象具有数以百万计的版本，请使用 S3 清单。S3 清单生成一份报告，用于提供存储桶中对象的平面文件列表。有关更多信息，请参阅 [使用 S3 清单对数据进行编目和分析](storage-inventory.md)。

要验证存储桶中是否存在大量受版本控制的对象，请使用 S3 Storage Lens 存储统计管理工具指标来查看**当前版本对象计数**、**非当前版本对象计数**和**删除标记对象计数**。有关 Storage Lens 存储统计管理工具指标的更多信息，请参阅[Amazon S3 Storage Lens 存储统计管理工具指标词汇表](storage_lens_metrics_glossary.md)。

Amazon S3 团队鼓励客户调查重复覆盖同一对象的应用程序（可能会为该对象创建数百万个版本），以确定应用程序是否正常工作。例如，如果某个应用程序每分钟都要覆盖同一个对象，那么在一周时间内创建的版本数量会超过一万个。我们建议，为每个对象存储的版本数不超过十万个。如果您的应用场景需要一个或多个对象的数百万个版本，请联系 AWS 支持 团队以获得帮助，从而确定更好的解决方案。

**最佳实践**  
为防止与版本控制相关的性能降级问题，建议您采用以下最佳实践：
+ 启用生命周期规则以使对象的先前版本过期。例如，您可以创建生命周期规则，以使非当前版本在对象变为非当前状态的 30 天后过期。如果您不想全部删除非当前版本，也可以保留多个非当前版本。有关更多信息，请参阅[设置 S3 生命周期配置](how-to-set-lifecycle-configuration-intro.md)。
+ 启用生命周期规则，以删除存储桶中没有关联数据对象的过期对象删除标记。有关更多信息，请参阅[删除过期对象删除标记](lifecycle-configuration-examples.md#lifecycle-config-conceptual-ex7)。

有关其他 Amazon S3 性能优化最佳实践，请参阅[最佳实践设计模式](optimizing-performance.md)。