

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

# 使用校验和实现数据完整性保护
<a name="s3-checksums"></a>

Amazon Simple Storage Service (Amazon S3) 允许您在上传对象时指定校验和。当您指定校验和时，校验和与对象一起存储，并且可以在下载对象时验证该校验和。

传输文件时，校验和可提供额外的数据层完整性。使用校验和，您可以通过确认收到文件与原始文件是否匹配来验证数据一致性。有关 Amazon S3 校验和的更多信息，请参阅 [Amazon Simple Storage Service 用户指南](https://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity.html)，包括[支持的算法](https://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity.html#using-additional-checksums)。

您可以灵活地选择最适合自己需求的算法，并让 SDK 计算校验和。或者，您也可以使用任一受支持的算法，提供预先计算好的校验和值。

**注意**  
 从的 1.4.0 版开始 适用于 Kotlin 的 AWS SDK，SDK 通过自动计算上传的`CRC32`校验和来提供默认的完整性保护。如果您未提供预先计算的校验和值，或者未指定 SDK 计算校验和时应使用的算法，则 SDK 会计算此校验和。   
SDK 还提供数据完整性保护的全局设置，您可以在外部进行设置，您可以在[AWS SDKs 和工具参考指南](https://docs.aws.amazon.com/sdkref/latest/guide/feature-dataintegrity.html)中阅读这些设置。

我们在两个请求阶段讨论校验和：上传对象和下载对象。

## 上传对象
<a name="use-service-S3-checksum-upload"></a>

您可以使用带请求参数的 [https://docs.aws.amazon.com/sdk-for-kotlin/api/latest/s3/aws.sdk.kotlin.services.s3/put-object.html](https://docs.aws.amazon.com/sdk-for-kotlin/api/latest/s3/aws.sdk.kotlin.services.s3/put-object.html) 函数，通过适用于 Kotlin 的 SDK 将对象上传到 Amazon S3。请求数据类型提供用于启用校验和计算的 `checksumAlgorithm` 属性。

以下代码段展示了上传具有 `CRC32` 校验和的对象的请求。当 SDK 发送请求时，它会计算 `CRC32` 校验和并上传对象。Amazon S3 将校验和与对象一起存储。

```
val request = PutObjectRequest {
    bucket = "{{amzn-s3-demo-bucket}}"
    key = "{{key}}"
    checksumAlgorithm = ChecksumAlgorithm.CRC32
}
```

如果您未在请求中提供校验和算法，则校验和行为将根据您使用的 SDK 版本而异，具体如下表所示。

**未提供校验和算法时的校验和行为**


| Kotlin SDK 版本 | 校验和行为 | 
| --- | --- | 
| 1.4.0 之前的版本 | SDK 不会自动计算基于 CRC 的校验和，也不会在请求中提供该值。 | 
| 1.4.0 或更高版本 | SDK 使用 `CRC32` 算法计算校验和，并在请求中提供该值。Amazon S3 通过计算自己的 `CRC32` 校验和并将其与 SDK 提供的校验和进行对比，从而验证传输的完整性。如果校验和匹配，则校验和将与对象一起保存。 | 

### 使用预先计算的校验和值
<a name="use-service-S3-checksum-upload-pre"></a>

与请求一起提供的预先计算校验和值会禁用 SDK 的自动计算，而是使用提供的值。

以下示例显示了具有预先计算的 SHA256校验和的请求。

```
val request = PutObjectRequest {
    bucket = "{{amzn-s3-demo-bucket}}"
    key = "{{key}}"
    body = ByteStream.fromFile(File("file_to_upload.txt"))
    checksumAlgorithm = ChecksumAlgorithm.SHA256
    checksumSha256 = "cfb6d06da6e6f51c22ae3e549e33959dbb754db75a93665b8b579605464ce299"
}
```

如果 Amazon S3 确定指定算法的校验和值不正确，服务就会返回错误响应。

### 分段上传
<a name="use-service-S3-checksum-upload-multi"></a>

您也可以将校验和用于分段上传。

 您必须在 `CreateMultipartUpload` 请求和每个 `UploadPart` 请求中指定校验和算法。最后一步，您必须在 `CompleteMultipartUpload` 中指定每个分段的校验和。以下示例展示了如何创建具有指定校验和算法的分段上传。

```
val multipartUpload = s3.createMultipartUpload {
    bucket = "{{amzn-s3-demo-bucket}}"
    key = "{{key}}"
    checksumAlgorithm = ChecksumAlgorithm.Sha1
}

val partFilesToUpload = listOf("data-part1.csv", "data-part2.csv", "data-part3.csv")

val completedParts = partFilesToUpload
    .mapIndexed { i, fileName ->
        val uploadPartResponse = s3.uploadPart {
            bucket = "amzn-s3-demo-bucket"
            key = "key"
            body = ByteStream.fromFile(File(fileName))
            uploadId = multipartUpload.uploadId
            partNumber = i + 1 // Part numbers begin at 1.
            checksumAlgorithm = ChecksumAlgorithm.Sha1
        }

        CompletedPart {
            eTag = uploadPartResponse.eTag
            partNumber = i + 1
            checksumSha1 = uploadPartResponse.checksumSha1
        }
    }

s3.completeMultipartUpload {
    uploadId = multipartUpload.uploadId
    bucket = "{{amzn-s3-demo-bucket}}"
    key = "{{key}}"
    multipartUpload {
        parts = completedParts
    }
}
```

## 下载对象
<a name="use-service-S3-checksum-download"></a>

使用 [getObject](https://docs.aws.amazon.com/sdk-for-kotlin/api/latest/s3/aws.sdk.kotlin.services.s3/-s3-client/get-object.html) 方法下载对象时，在以下情况下 SDK 会自动验证校验和：如果适用于 `GetObjectRequest` 的生成器的 `checksumMode` 属性设置为 `ChecksumMode.Enabled`。

以下代码段中的请求引导 SDK 通过计算校验和并比较值来验证响应中的校验和。

```
val request = GetObjectRequest {
    bucket = "{{amzn-s3-demo-bucket}}"
    key = "{{key}}"
    checksumMode = ChecksumMode.Enabled
}
```

**注意**  
如果上传对象时没有使用校验和，则不会进行验证。

如果您使用的是 1.4.0 或更高版本的 SDK，SDK 会自动检查 `getObject` 请求的完整性，而无需将 `checksumMode = ChecksumMode.Enabled` 添加到请求中。

### 异步验证
<a name="service-s3-checksum-getObject-kotlin-asyncValidation"></a>

由于适用于 Kotlin 的 SDK 在从 Amazon S3 下载对象时使用流式响应，因此将在您使用该对象时计算校验和。因此，您*必须*使用该对象才能验证校验和。

以下示例展示了如何通过充分使用响应来验证校验和。

```
val request = GetObjectRequest {
    bucket = "{{amzn-s3-demo-bucket}}"
    key = "{{key}}"
    checksumMode = checksumMode.Enabled
}

val response = s3Client.getObject(request) {
    println(response.body?.decodeToString()) // Fully consume the object.
    // The checksum is valid.
}
```

相比之下，以下示例中的代码并未以任何方式使用该对象，因此不会验证校验和。

```
s3Client.getObject(request) {
    println("Got the object.")
}
```

如果由 SDK 计算的校验和与随响应一起发送的预期校验和不匹配，SDK 就会抛出 `ChecksumMismatchException`。