教程:通过分段上传来上传对象并验证其数据完整性 - Amazon Simple Storage Service

教程:通过分段上传来上传对象并验证其数据完整性

分段上传允许将单个对象作为一组分段上传。每个分段都是对象数据的连续部分。您可以独立上传以及按任意顺序上传这些对象分段。如果任意分段传输失败,可以重新传输该分段且不会影响其他分段。上传完所有的对象分段后,Amazon S3 将汇集这些分段并创建对象。一般而言,如果您的对象大小达到了 100 MB,您应该考虑使用分段上传,而不是在单个操作中上传对象。有关分段上传的更多信息,请参阅使用分段上传来上传和复制对象。有关分段上传的相关限制,请参阅 Amazon S3 分段上传限制

可以使用校验和来验证资产在复制时是否未被更改。执行校验和包括使用算法按顺序迭代文件中的每个字节。Amazon S3 提供了多个校验和选项,用于检查数据的完整性。我们建议您将这些完整性检查作为持久性最佳实践加以执行,并确认每个字节在传输过程中都未经更改。Amazon S3 还支持以下算法:SHA-1、SHA-256、CRC32 和 CRC32C。Amazon S3 使用其中一个或多个算法来计算额外的校验和值,并将其存储为对象元数据的一部分。有关校验和的更多信息,请参阅检查对象完整性

目标

在本教程中,您将学习如何在 AWS 命令行界面(AWS CLI)中使用分段上传和额外的 SHA-256 校验和将对象上传到 Amazon S3。您还将学习如何通过计算已上传对象的 MD5 哈希值和 SHA-256 校验和,来检查对象的数据完整性。

先决条件

  • 在开始本教程之前,请确保您有权访问要上传到的 Amazon S3 存储桶。有关更多信息,请参阅 创建桶

  • 您必须安装并配置了 AWS CLI。如果未安装 AWS CLI,请参阅《AWS Command Line Interface用户指南》中的 Install or update to the latest version of the AWS CLI

  • 或者,您可以从控制台中使用 AWS CloudShell 运行 AWS CLI 命令。AWS CloudShell 是一个基于浏览器、预先经过身份验证的 Shell,您可以直接从 AWS Management Console中启动它。有关更多信息,请参阅《AWS CloudShell 用户指南》中的 What is CloudShell?Getting started with AWS CloudShell

步骤 1:创建大文件

如果您已经准备好要上传的文件,则可以在本教程中使用该文件。否则,请使用以下步骤创建一个 15 MB 的文件。有关分段上传的相关限制,请参阅 Amazon S3 分段上传限制

创建大文件

根据您使用的操作系统,使用以下命令之一来创建文件。

Linux 或 macOS

要创建 15 MB 的文件,请打开本地终端并运行以下命令:

dd if=/dev/urandom of=census-data.bin bs=1M count=15

此命令创建一个名为 census-data.bin 的文件,其中填充了随机字节,大小为 15 MB。

Windows

要创建 15 MB 的文件,请打开本地终端并运行以下命令:

fsutil file createnew census-data.bin 15728640

此命令创建一个名为 census-data.bin 的文件,其中包含任意数据,大小为 15 MB(15728640 字节)。

步骤 2:将文件拆分为多个文件

要执行分段上传,必须将大文件拆分为若干较小的分段。然后,可以使用分段上传过程来上传较小的分段。此步骤演示如何将步骤 1 中创建的大文件拆分为较小的分段。以下示例使用名为 census-data.bin 的 15 MB 文件。

将大文件拆分为多个分段

Linux 或 macOS

要将大文件分成 5 MB 的分段,请使用 split 命令。打开终端并运行以下命令:

split -b 5M -d census-data.bin census-part

此命令将 census-data.bin 拆分成名为 census-part** 的 5 MB 分段,其中 ** 是从 00 开始的数字后缀。

Windows

要拆分大文件,请使用 PowerShell。打开 Powershell 并运行以下命令:

$inputFile = "census-data.bin" $outputFilePrefix = "census-part" $chunkSize = 5MB $fs = [System.IO.File]::OpenRead($inputFile) $buffer = New-Object byte[] $chunkSize $fileNumber = 0 while ($fs.Position -lt $fs.Length) { $bytesRead = $fs.Read($buffer, 0, $chunkSize) $outputFile = "{0}{1:D2}" -f $outputFilePrefix, $fileNumber $fileStream = [System.IO.File]::Create($outputFile) $fileStream.Write($buffer, 0, $bytesRead) $fileStream.Close() $fileNumber++ } $fs.Close()

此 PowerShell 脚本以 5 MB 大小的分块读取大文件,并将每个分块写入一个带有数字后缀的新文件。

运行相应的命令后,您应该会在执行该命令的目录中看到各个分段。每个分段都有一个与其分段编号对应的后缀,例如:

census-part00 census-part01 census-part02

步骤 3:创建分段上传并指定额外的校验和

要开始分段上传过程,您需要创建分段上传请求。此步骤包括启动分段上传以及为数据完整性指定额外的校验和。以下示例使用 SHA-256 校验和。如果您想要提供描述正上传的对象的任何元数据,必须在请求中提供它以便开始分段上传。

注意

在本步骤和后续步骤中,本教程使用 SHA-256 额外算法。您可以选择为这些步骤使用其他的额外校验和,例如 CRC32、CRC32C 或 SHA-1。如果使用不同的算法,则必须在整个教程步骤中都使用该算法。

开始分段上传

在终端中,使用以下 create-multipart-upload 命令开始存储桶的分段上传。将 amzn-s3-demo-bucket1 替换为实际存储桶名称。另外,请用您选择的文件名替换 census_data_file。上传完成后,此文件名将成为对象键。

aws s3api create-multipart-upload --bucket amzn-s3-demo-bucket1 --key 'census_data_file' --checksum-algorithm sha256

如果您的请求执行成功,您将看到如下 JSON 输出:

{ "ServerSideEncryption": "AES256", "ChecksumAlgorithm": "SHA256", "Bucket": "amzn-s3-demo-bucket1", "Key": "census_data_file", "UploadId": "cNV6KCSNANFZapz1LUGPC5XwUVi1n6yUoIeSP138sNOKPeMhpKQRrbT9k0ePmgoOTCj9K83T4e2Gb5hQvNoNpCKqyb8m3.oyYgQNZD6FNJLBZluOIUyRE.qM5yhDTdhz" }
注意

当您发送请求以开始分段上传时,Amazon S3 将返回具有上传 ID 的响应,此 ID 是分段上传的唯一标识符。无论您何时上传分段、列出分段、完成上传或停止上传,您都必须包括此上传 ID。后续步骤需要用到 UploadIdKeyBucket 值,因此请务必保存这些值。

此外,如果您将分段上传与额外的校验和结合使用,则分段编号必须是连续的。如果您使用不连续的分段编号,则 complete-multipart-upload 请求可能会导致 HTTP 500 Internal Server Error

步骤 4:上传分段上传的分段

在此步骤中,您将分段上传的各个分段上传到 S3 存储桶。使用 upload-part 命令单独上传每个分段。此过程要求为每个分段指定上传 ID、分段编号和要上传的文件。

上传分段
  1. 上传分段时,除了上传 ID,还必须使用 --part-number 参数来指定分段编号。您可以选择 1 和 10000 之间的任意分段编号。分段编号在您正在上传的对象中唯一地识别分段及其位置。您选择的分段编号必须为连续序列(例如,它可以是 1、2 或 3)。如果您使用之前上传的分段的同一分段编号上传新分段,则之前上传的分段将被覆盖。

  2. 使用 upload-part 命令来上传分段上传的每个分段。--upload-id步骤 3create-multipart-upload 命令创建的输出内容相同。要上传数据的第一个分段,请使用以下命令:

    aws s3api upload-part --bucket amzn-s3-demo-bucket1 --key 'census_data_file' --part-number 1 --body census-part00 --upload-id "cNV6KCSNANFZapz1LUGPC5XwUVi1n6yUoIeSP138sNOKPeMhpKQRrbT9k0ePmgoOTCj9K83T4e2Gb5hQvNoNpCKqyb8m3.oyYgQNZD6FNJLBZluOIUyRE.qM5yhDTdhz" --checksum-algorithm SHA256

    完成每个 upload-part 命令后,您应该会看到类似以下示例的输出:

    { "ServerSideEncryption": "AES256", "ETag": "\"e611693805e812ef37f96c9937605e69\"", "ChecksumSHA256": "QLl8R4i4+SaJlrl8ZIcutc5TbZtwt2NwB8lTXkd3GH0=" }
  3. 对于后续分段,相应地递增分段编号:

    aws s3api upload-part --bucket amzn-s3-demo-bucket1 --key 'census_data_file' --part-number <part-number> --body <file-path> --upload-id "<your-upload-id>" --checksum-algorithm SHA256

    例如,使用以下命令来上传第二个分段:

    aws s3api upload-part --bucket amzn-s3-demo-bucket1 --key 'census_data_file' --part-number 2 --body census-part01 --upload-id "cNV6KCSNANFZapz1LUGPC5XwUVi1n6yUoIeSP138sNOKPeMhpKQRrbT9k0ePmgoOTCj9K83T4e2Gb5hQvNoNpCKqyb8m3.oyYgQNZD6FNJLBZluOIUyRE.qM5yhDTdhz" --checksum-algorithm SHA256

    Amazon S3 将在响应的标头中返回每个已上传分段的实体标签(ETag)和额外的校验和。

  4. 继续使用 upload-part 命令,直到上传了对象的所有分段。

步骤 5:列出分段上传的所有分段

要完成分段上传,您需要列出在这个特定分段上传任务中已经上传的所有分段。list-parts 命令的输出提供了诸如存储桶名称、键、上传 ID、分段编号、eTag、额外的校验和等信息。将此输出保存在文件中会很有帮助,这样您就可以在完成分段上传过程的下一步中使用它。可以使用以下方法创建名为 parts.json 的 JSON 输出文件。

创建列出所有分段的文件
  1. 要生成包含所有已上传分段详细信息的 JSON 文件,请使用以下 list-parts 命令。将 amzn-s3-demo-bucket1 替换为实际的存储桶名称,并将 <your-upload-id> 替换为您在步骤 3 中收到的上传 ID。有关 list-parts 命令的更多信息,请参阅《AWS Command Line Interface 用户指南》中的 list-parts

    aws s3api list-parts --bucket amzn-s3-demo-bucket1 --key 'census_data_file' --upload-id <your-upload-id> --query '{Parts: Parts[*].{PartNumber: PartNumber, ETag: ETag, ChecksumSHA256: ChecksumSHA256}}' --output json > parts.json

    这样会生成一个名为 parts.json 的新文件。该文件采用 JSON 格式,包含所有已上传分段的信息。parts.json 文件包含分段上传的每个分段的基本信息,例如分段编号及其相应的 ETag 值,这些是完成分段上传过程所必需的。

  2. 使用任何文本编辑器或通过终端打开 parts.json。以下是示例输出:

    { "Parts": [ { "PartNumber": 1, "ETag": "\"3c3097f89e2a2fece47ac54b243c9d97\"", "ChecksumSHA256": "fTPVHfyNHdv5VkR4S3EewdyioXECv7JBxN+d4FXYYTw=" }, { "PartNumber": 2, "ETag": "\"03c71cc160261b20ab74f6d2c476b450\"", "ChecksumSHA256": "VDWTa8enjOvULBAO3W2a6C+5/7ZnNjrnLApa1QVc3FE=" }, { "PartNumber": 3, "ETag": "\"81ae0937404429a97967dffa7eb4affb\"", "ChecksumSHA256": "cVVkXehUlzcwrBrXgPIM+EKQXPUvWist8mlUTCs4bg8=" } ] }

步骤 6:完成分段上传

在分段上传的所有分段都上传完毕并且列出分段信息后,最后一步是完成分段上传。此步骤会在 S3 存储桶中将所有上传的分段合并成单个对象。

注意

您可以在调用 complete-multipart-upload 之前,通过在请求中包含 --checksum-sha256 来计算对象的校验和。如果校验和不匹配,Amazon S3 就会让请求失败。有关更多信息,请参阅《AWS Command Line Interface 用户指南》中的 complete-multipart-upload

完成分段上传

要最终完成分段上传,请使用 complete-multipart-upload 命令。此命令需要用到步骤 5 中创建的 parts.json 文件、存储桶名称以及上传 ID。将 <amzn-s3-demo-bucket1> 替换为存储桶名称,并将 <your-upload-id> 替换为 parts.json 的上传 ID。

aws s3api complete-multipart-upload --multipart-upload file://parts.json --bucket amzn-s3-demo-bucket1 --key 'census_data_file' --upload-id <your-upload-id>

以下是示例输出:

{ "ServerSideEncryption": "AES256", "Location": "https://amzn-s3-demo-bucket1.s3.us-east-2.amazonaws.com/census_data_file", "Bucket": "amzn-s3-demo-bucket1", "Key": "census_data_file", "ETag": "\"f453c6dccca969c457efdf9b1361e291-3\"", "ChecksumSHA256": "aI8EoktCdotjU8Bq46DrPCxQCGuGcPIhJ51noWs6hvk=-3" }
注意

此时请勿删除各个分段文件。您还需要使用各个分段来对它们执行校验和,从而验证合并在一起的对象的完整性。

步骤 7:确认对象上传到存储桶

完成分段上传后,您可以验证对象已成功地上传到 S3 存储桶。要列出存储桶中的对象并确认新上传的文件已经存在,请使用 list-objects-v2 命令。

列出上传的对象

要列出存储桶中的对象,请使用 list-objects-v2 命令。将 amzn-s3-demo-bucket1 替换为实际存储桶名称:

aws s3api list-objects-v2 --bucket amzn-s3-demo-bucket1

此命令将返回存储桶中对象的列表。在对象列表中查找您上传的文件(例如 census_data_file)。

有关更多信息,请参阅《AWS Command Line Interface用户指南》list-objects-v2 命令的 Examples 部分。

步骤 8:使用 MD5 校验和验证对象完整性

在上传对象时,可以指定校验和算法以供 Amazon S3 使用。默认情况下,Amazon S3 将 MD5 字节摘要存储为对象的 ETag。对于分段上传,ETag 不是完整对象的校验和,而是每个单独分段的校验和组合。

使用 MD5 校验和验证对象完整性
  1. 要检索已上传对象的 ETag,请执行 head-object 请求:

    aws s3api head-object --bucket amzn-s3-demo-bucket1 --key census_data_file

    以下是示例输出:

    { "AcceptRanges": "bytes", "LastModified": "2024-07-26T19:04:13+00:00", "ContentLength": 16106127360, "ETag": "\"f453c6dccca969c457efdf9b1361e291-3\"", "ContentType": "binary/octet-stream", "ServerSideEncryption": "AES256", "Metadata": {} }

    此 etag 的末尾附有“-3”。这表示对象是使用分段上传分为三个分段进行上传的。

  2. 接下来,使用 md5sum 命令计算每个分段的 MD5 校验和。请确保提供指向分段文件的正确路径:

    md5sum census-part*

    以下是示例输出:

    e611693805e812ef37f96c9937605e69 census-part00 63d2d5da159178785bfd6b6a5c635854 census-part01 95b87c7db852451bb38b3b44a4e6d310 census-part02
  3. 对于此步骤,手动将 MD5 哈希值合并为一个字符串。然后,运行以下命令,将字符串转换为二进制并计算二进制值的 MD5 校验和:

    echo "e611693805e812ef37f96c9937605e6963d2d5da159178785bfd6b6a5c63585495b87c7db852451bb38b3b44a4e6d310" | xxd -r -p | md5sum

    以下是示例输出:

    f453c6dccca969c457efdf9b1361e291 -

    此哈希值应与步骤 1 中原始 ETag 值的哈希值相匹配,这可验证 census_data_file 对象的完整性。

当您指示 Amazon S3 使用其他校验和时,Amazon S3 会计算每个分段的校验和值并存储这些值。如果您想检索仍在进行的分段上传的各个分段的校验和值,可以使用 list-parts

有关校验和如何处理分段上传对象的更多信息,请参阅检查对象完整性

步骤 9:使用额外的校验和验证对象完整性

在本步骤中,教程使用 SHA-256 作为额外的校验和来验证对象完整性。如果您使用了不同的额外校验和,请改用该校验和值。

使用 SHA256 验证对象完整性
  1. 在终端中运行以下命令(包括 --checksum-mode enabled 参数),以显示对象的 ChecksumSHA256 值:

    aws s3api head-object --bucket amzn-s3-demo-bucket1 --key census_data_file --checksum-mode enabled

    以下是示例输出:

    { "AcceptRanges": "bytes", "LastModified": "2024-07-26T19:04:13+00:00", "ContentLength": 16106127360, "ChecksumSHA256": "aI8EoktCdotjU8Bq46DrPCxQCGuGcPIhJ51noWs6hvk=-3", "ETag": "\"f453c6dccca969c457efdf9b1361e291-3\"", "ContentType": "binary/octet-stream", "ServerSideEncryption": "AES256", "Metadata": {} }
  2. 使用以下命令将各个分段的 ChecksumSHA256 值解码为 base64,然后将其保存到名为 outfile 的二进制文件中。这些值可以在 parts.json 文件中找到。将示例 base64 字符串替换为实际的 ChecksumSHA256 值。

    echo "QLl8R4i4+SaJlrl8ZIcutc5TbZtwt2NwB8lTXkd3GH0=" | base64 --decode >> outfile echo "xCdgs1K5Bm4jWETYw/CmGYr+m6O2DcGfpckx5NVokvE=" | base64 --decode >> outfile echo "f5wsfsa5bB+yXuwzqG1Bst91uYneqGD3CCidpb54mAo=" | base64 --decode >> outfile
  3. 运行以下命令计算 outfile 的 SHA256 校验和:

    sha256sum outfile

    以下是示例输出:

    688f04a24b42768b6353c06ae3a0eb3c2c50086b8670f221279d67a16b3a86f9 outfile

    在下一步中,获取哈希值并将其转换为二进制值。此二进制值应与步骤 1 中的 ChecksumSHA256 值相匹配。

  4. 步骤 3 中的 SHA256 校验和转换为二进制,然后将其编码为 base64,来验证它与步骤 1 中的 ChecksumSHA256 值相匹配:

    echo "688f04a24b42768b6353c06ae3a0eb3c2c50086b8670f221279d67a16b3a86f9" | xxd -r -p | base64

    以下是示例输出:

    aI8EoktCdotjU8Bq46DrPCxQCGuGcPIhJ51noWs6hvk=

    此输出应确认 base64 输出与 head-object 命令输出中的 ChecksumSHA256 值相匹配。如果输出与校验和值匹配,则该对象有效。

重要
  • 当您指示 Amazon S3 使用额外的校验和时,Amazon S3 会计算每个分段的校验和值并存储这些值。

  • 如果您想检索仍在进行的分段上传的各个分段的校验和值,可以使用 list-parts 命令。

步骤 10:清除资源

如果要清理在本教程中创建的文件,请使用以下方法。有关删除上传到 S3 存储桶的文件的说明,请参阅删除 Amazon S3 对象

删除步骤 1 中创建的本地文件:

要删除您为分段上传创建的文件,请从工作目录中运行以下命令:

rm census-data.bin census-part* outfile parts.json