如何使用條件式寫入防止物件覆寫 - Amazon Simple Storage Service

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

如何使用條件式寫入防止物件覆寫

透過使用條件式寫入,您可以將額外的標頭新增至 WRITE 請求,以指定 Amazon S3 操作的先決條件。若要有條件地寫入物件,請新增 HTTP If-None-MatchIf-Match 標頭。

If-None-Match 標頭會驗證您的儲存貯體中不存在具有相同金鑰名稱的物件,以防止覆寫現有資料。

或者,您也可以新增 If-Match 標頭,在寫入物件之前檢查物件的實體標籤 (ETag)。透過此標頭,Amazon S3 會將提供的 ETag 值與 S3 中物件的 ETag 值進行比較。如果 ETag 值不相符,操作就會失敗。

儲存貯體擁有者可以使用儲存貯體政策,對上傳的物件強制執行條件式寫入。如需詳細資訊,請參閱在 Amazon S3 儲存貯體上強制執行條件式寫入

注意

若要使用條件式寫入,您必須透過 HTTPS (TLS) 提出請求,或使用 AWS 第 4 版簽署程序來簽署請求。

如何根據金鑰名稱防止物件覆寫

您可以使用 HTTP If-None-Match 條件式標頭,在建立物件之前,根據物件的金鑰名稱,檢查物件是否已存在於指定的儲存貯體中。當您將物件上傳至 Amazon S3 時,請指定金鑰名稱 (儲存貯體中物件之區分大小寫的唯一識別碼)。在沒有 HTTP If-None-Match 標頭的情況下,如果您上傳的物件使用了與無版本控制或已暫停版本控制之儲存貯體中相同的金鑰名稱,則會覆寫該物件。在使用版本控制的儲存貯體中,最近上傳的物件會成為物件的目前版本。使用 HTTP If-None-Match 標頭的條件式寫入會在 WRITE 操作期間檢查物件是否存在。如果在儲存貯體中找到相同的金鑰名稱,操作就會失敗。如需使用金鑰名稱的詳細資訊,請參閱命名 Amazon S3 物件

若要使用 HTTP If-None-Match 標頭執行條件式寫入,您必須具有 s3:PutObject 許可。這可讓呼叫者檢查儲存貯體中是否存在物件。If-None-Match 標頭必須有 * (星號) 值。

您可以搭配下列 API 使用 If-None-Match 標頭:

下列 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 "*"

如需詳細資訊,請參閱 AWS CLI 命令參考中的 put-object

如需 的相關資訊 AWS CLI,請參閱AWS Command Line Interface 《 使用者指南》中的什麼是 AWS Command Line Interface?

如果物件已變更,如何防止覆寫

物件的 ETag 是物件的唯一字串,反映物件內容的變更。您可以使用 If-Match 標頭,將 Amazon S3 儲存貯體中物件的 ETag 值與您在 WRITE 操作期間提供的 ETag 值進行比較。如果 ETag 值不相符,操作就會失敗。如需 ETag 的詳細資訊,請參閱使用 Content-MD5 和 ETag 驗證上傳的物件

若要使用 HTTP If-Match 標頭執行條件式寫入,您必須具有 s3:PutObjects3:GetObject 許可。這可讓呼叫者檢查 ETag 並確認儲存貯體中物件的狀態。If-Match 標頭必須有字串形式的 ETag 值。

您可以搭配下列 API 使用 If-Match 標頭:

下列 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"

如需詳細資訊,請參閱 AWS CLI 命令參考中的 put-object

如需 的相關資訊 AWS CLI,請參閱AWS Command Line Interface 《 使用者指南》中的什麼是 AWS 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-MatchIf-Match 標頭產生 412 Precondition Failed 回應。

兩個用戶端使用相同金鑰名稱寫入項目的範例。一個使用 UploadPart 進行 MPU,另一個使用 PutObject 和條件式寫入。之後啟動的 CompleteMultipartUpload 操作會失敗。
分段上傳期間的並行刪除

如果刪除請求在條件式寫入請求完成之前成功,Amazon S3 會針對寫入操作傳回 409 Conflict404 Not Found 回應。這是因為先前啟動的刪除請求會優先於條件式寫入操作。在這種情況下,您必須啟動新的分段上傳。

注意

此案例會針對 If-None-Match 標頭產生 409 Conflict 回應,並針對 If-Match 標頭產生 404 Not Found 回應。

兩個用戶端的範例,一個使用分段上傳,另一個在 MPU 開始之後傳送刪除請求。刪除請求在條件式寫入開始之前完成。
注意

為了將儲存費用降至最低,建議您使用 AbortIncompleteMultipartUpload 動作,將生命週期規則設定為在指定天數後刪除不完整的分段上傳。如需詳細了解生命週期規則的建立,以刪除不完整分段上傳,請參閱設定儲存貯體生命週期組態,刪除不完整分段上傳