如何使用有条件写入来防止对象覆盖
通过使用有条件写入,可以向 WRITE
请求中添加一个额外的标头,以便为 Amazon S3 操作指定前提条件。要有条件地写入对象,请添加 HTTP If-None-Match
或 If-Match
标头。
If-None-Match
标头通过验证存储桶中尚不存在具有相同键名称的对象,来防止覆盖现有数据。
或者,您可以在写入对象之前添加 If-Match
标头来检查对象的实体标签(ETag)。通过此标头,Amazon S3 将提供的 ETag 值与 S3 中对象的 ETag 值进行比较。如果 ETag 值不匹配,则操作会失败。
存储桶拥有者可以使用存储桶策略对上传的对象强制实施有条件写入。有关更多信息,请参阅 强制对 Amazon S3 存储桶实施有条件写入。
注意
要使用有条件写入,必须通过 HTTPS(TLS)发出请求,或使用 Amazon 签名版本 4 对请求进行签名。
如何防止基于键名称的对象覆盖
在创建对象之前,可以使用 HTTP If-None-Match
有条件标头,根据其键名称检查指定存储桶中是否已存在该对象。在将对象上传到 Amazon S3 时,请指定键名称:存储桶中对象的唯一且区分大小写的标识符。在不使用 If-None-Match
标头时,如果您在未受版本控制或已暂停版本控制的存储桶中上传具有相同键名称的对象,则该对象将被覆盖。在受版本控制的存储桶中,最近上传的对象成为对象的当前版本。具有 HTTP If-None-Match
标头的有条件写入将在 WRITE
操作期间检查对象是否存在。如果在存储桶中找到相同的键名称,则操作失败。有关使用键名称的更多信息,请参阅为 Amazon S3 对象命名。
要执行具有 HTTP If-None-Match
标头的有条件写入,您必须拥有 s3:PutObject
权限。这使调用方能够检查存储桶中是否存在对象。If-None-Match
标头需要 *(星号)值。
您可以将 If-None-Match
标头与以下 API 结合使用:
以下 put-object
示例命令尝试对键名称为 dir-1/my_images.tar.bz2
的对象执行有条件写入。
aws s3api put-object --bucket
amzn-s3-demo-bucket
--key dir-1/my_images.tar.bz2 --body my_images.tar.bz2 --if-none-match "*"
有关更多信息,请参阅 Amazon CLI 命令参考 中的 put-object
有关 Amazon CLI 的更多信息,请参阅《Amazon Command Line Interface 用户指南》中的什么是 Amazon Command Line Interface?。
如果对象已更改,如何防止被覆盖
对象的 ETag 是该对象所特有的字符串,它反映了对象内容的变化。可以使用 If-Match
标头将 Amazon S3 存储桶中对象的 ETag 值与您在 WRITE
操作期间提供的值进行比较。如果 ETag 值不匹配,则操作会失败。有关 ETag 的更多信息,请参阅使用 Content-MD5 和 ETag 验证上传的对象。
要执行具有 HTTP If-Match
标头的有条件写入,您必须拥有 s3:PutObject
和 s3:GetObject
权限。这使调用方能够检查 ETag 并验证存储桶中对象的状态。If-Match
标头要求将 ETag 值作为字符串。
您可以将 If-Match
标头与以下 API 结合使用:
以下 put-object
示例命令尝试使用提供的 ETag 值 6805f2cfc46c0f04559748bb039d69ae
执行有条件写入。
aws s3api put-object --bucket
amzn-s3-demo-bucket
--key dir-1/my_images.tar.bz2 --body my_images.tar.bz2 --if-match "6805f2cfc46c0f04559748bb039d69ae
"
有关更多信息,请参阅 Amazon CLI 命令参考 中的 put-object
有关 Amazon CLI 的更多信息,请参阅《Amazon Command Line Interface 用户指南》中的什么是 Amazon Command Line Interface?。
有条件写入行为
- 具有
If-None-Match
标头的有条件写入 -
具有
If-None-Match
标头的有条件写入会针对存储桶中的现有对象进行评估。如果存储桶中不存在具有相同键名称的现有对象,则写入操作将成功并导致200 OK
响应。如果存在现有对象,则写入操作将失败,并导致412 Precondition Failed
响应。对于启用了版本控制的存储桶,如果没有同名的当前对象版本,或者当前对象版本是删除标记,则写入操作将成功。否则,它会导致写入操作失败和
412 Precondition Failed
响应。如果对同一个对象名称进行多个有条件写入,则第一个要完成的写入操作将成功。然后,Amazon S3 使后续写入失败并生成
412 Precondition Failed
响应。如果在针对某个对象的有条件写入操作完成之前,对于该对象的删除请求获得成功,则在并发请求的情况下也可能收到
409 Conflict
响应。将有条件写入与PutObject
结合使用时,可能会在收到409 Conflict
错误后重试上传。使用CompleteMultipartUpload
时,必须使用CreateMultipartUpload
重新启动分段上传,以便在收到409 Conflict
错误后再次上传对象。 - 具有
If-Match
标头的有条件写入 -
If-Match
标头会针对存储桶中的现有对象进行评估。如果存在具有相同键名称和匹配 ETag 的现有对象,则写入操作将成功并导致200 OK
响应。如果 ETag 不匹配,则写入操作将失败并导致412 Precondition Failed
响应。如果是并发请求,您也可能收到
409 Conflict
响应。如果在针对对象的有条件写入操作完成之前,对于对象的并发删除请求获得成功,您将收到
404 Not Found
响应,因为对象键不再存在。收到404 Not Found
响应后,您应该重新上传对象。如果没有同名的当前对象版本,或者当前对象版本是删除标记,则该操作失败并出现
404 Not Found
错误。
有条件写入场景
考虑以下场景,即两个客户端对同一个存储桶运行操作。
分段上传期间的有条件写入
有条件写入不考虑任何正在进行的分段上传请求,因为这些对象还不是完全写入的对象。请考虑以下示例,其中客户端 1 正在使用分段上传来上传对象。在分段上传期间,客户端 2 能够通过有条件写入操作成功写入相同的对象。随后,当客户端 1 尝试使用有条件写入完成分段上传时,上传将失败。
注意
这种情况将导致 If-None-Match
和 If-Match
标头都得到 412 Precondition Failed
响应。

分段上传期间的并发删除
如果在有条件写入请求可以完成之前,删除请求获得成功,则 Amazon S3 为写入操作返回 409 Conflict
或 404 Not Found
响应。这是因为更早启动的删除请求优先于有条件写入操作。在这种情况下,您必须启动新的分段上传。
注意
这种情况将对 If-None-Match
标头导致 409 Conflict
响应和对 If-Match
标头导致 404 Not Found
响应。

注意
为了最大程度地降低存储成本,我们建议您配置生命周期规则,以便使用 AbortIncompleteMultipartUpload
操作在指定的天数后删除未完成的分段上传。有关创建生命周期规则以删除未完成的分段上传的更多信息,请参阅配置存储桶生命周期配置以删除未完成的分段上传。