對象層級保留原則(ObjectWorm)提供對象粒度的WORM(Write Once Read Many)合規保留能力。與 Bucket層級保留原則(BucketWorm)對Bucket內所有Object統一保護不同,ObjectWorm支援為每個Object設定獨立的保留模式和保留到期日,滿足金融、醫學等行業的精細化合規儲存需求。
該功能目前為邀測功能,如需使用,請聯絡支援人員申請開通。當前僅支援華東1(杭州)、西南1(成都)、華南1(深圳)、華南3(廣州)、華北1(青島)、華北2(北京)、華北5(呼和浩特)、華南2(河源)、中國香港、德國(法蘭克福)、日本(東京)、韓國(首爾)、新加坡、馬來西亞(吉隆坡)、印尼(雅加達)、菲律賓(馬尼拉)、泰國(曼穀)、沙特(利雅得)、阿聯酋(杜拜)地區。
功能概述
Object Worm在Bucket層級開啟後,支援為每個新上傳的Object自動應用預設保留原則,也支援為單個已上傳的Object設定獨立的保留原則。Object層級的策略優先順序高於Bucket預設策略。
當前僅支援合規模式(COMPLIANCE),即在保留期限內任何使用者(包括根使用者)都不能刪除或覆蓋寫受保護的Object版本,保留到期日只能延長不能縮短。
Bucket Worm與Object Worm
對比項 | Bucket層級保留原則(BucketWorm) | 對象層級保留原則(ObjectWorm) |
保護範圍 | 整個儲存空間內所有對象 | 單個對象粒度 |
配置方式 | Bucket級開關,對Bucket內所有檔案(存量和增量)統一生效 | Bucket級開關 + 可選預設策略。新上傳檔案繼承預設策略,也可配置獨立的保留原則(優先順序更高)。存量檔案需單獨配置。 |
保留時間 | 相對保留天數(基於對象最後修改時間 + 保留天數) | 絕對保留到期日(RetainUntilDate),精確到秒 |
互斥關係 | Bucket Worm和Object Worm不支援同時開啟,二者互斥。 | |
前提條件
Bucket已開啟版本控制。Object Worm強依賴版本控制功能,未開啟版本控制時無法開啟Object Worm。開啟Object Worm後,版本控制無法關閉。
Bucket未開啟Bucket層級保留原則(BucketWorm)。Object Worm與Bucket Worm互斥,不支援同時開啟。
開啟Object Worm並配置保留原則
在Bucket上開啟對象層級保留原則,以防止特定檔案在一定時間內被刪除或被覆蓋寫。功能開啟後,可針對單個新上傳的對象或者單個已上傳的對象單獨配置保留原則,使用更加靈活。
此操作無法復原,開啟後無法關閉Object Worm功能,且版本控制也無法關閉。請確認後再操作。
控制台
登入OSS管理主控台。
在左側導覽列,單擊Bucket列表,然後單擊目標Bucket名稱。
在左側導覽列,選擇。
單擊開啟按鈕。
在預設保留原則配置中,按需配置以下參數:
暫不設定:不設定預設保留原則,上傳到 Bucket 中的對象不會自動附加預設保留規則。
合規模式(Compliance Mode):合規模式下,保留期內任何使用者(包括根使用者)都無法刪除或覆蓋寫對象。
保留時間:輸入保留時間長度數字,選擇單位為天或年。
單擊儲存,在二次確認彈窗中輸入確認資訊完成開啟。
ossutil
為儲存空間examplebucket開啟對象層級保留原則,並配置合規模式、預設保留天數為1天。
使用XML設定檔,object-worm-configuration.xml內容如下:
<?xml version="1.0" encoding="UTF-8"?>
<ObjectWormConfiguration>
<ObjectWormEnabled>Enabled</ObjectWormEnabled>
<Rule>
<DefaultRetention>
<Mode>COMPLIANCE</Mode>
<Days>1</Days>
</DefaultRetention>
</Rule>
</ObjectWormConfiguration>命令樣本如下:
ossutil api put-bucket-object-worm-configuration --bucket examplebucket --object-worm-configuration file://object-worm-configuration.xmlSDK
以下程式碼範例示範如何通過SDK開啟Object Worm並配置預設保留原則。
Python
import argparse
import alibabacloud_oss_v2 as oss
parser = argparse.ArgumentParser(description="put bucket object worm configuration sample")
parser.add_argument('--region', help='The region in which the bucket is located.', required=True)
parser.add_argument('--bucket', help='The name of the bucket.', required=True)
parser.add_argument('--endpoint', help='The domain names that other services can use to access OSS')
parser.add_argument('--mode', help='Object-level retention strategy pattern. Valid values: GOVERNANCE, COMPLIANCE', default='GOVERNANCE')
parser.add_argument('--days', help='Object-level retention policy days (max 36500)', type=int)
parser.add_argument('--years', help='Bucket object level retention policy years (max 100)', type=int)
def main():
args = parser.parse_args()
# Loading credentials values from the environment variables
credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()
# Using the SDK's default configuration
cfg = oss.config.load_default()
cfg.credentials_provider = credentials_provider
cfg.region = args.region
if args.endpoint is not None:
cfg.endpoint = args.endpoint
client = oss.Client(cfg)
# Create default retention settings
default_retention = oss.ObjectWormConfigurationRuleDefaultRetention(
mode=args.mode,
days=args.days,
# days and years can only appear once
# years=args.years,
)
# Create rule container
rule = oss.ObjectWormConfigurationRule(
default_retention=default_retention,
)
# Create configuration
config = oss.ObjectWormConfiguration(
object_worm_enabled='Enabled',
rule=rule,
)
result = client.put_bucket_object_worm_configuration(oss.PutBucketObjectWormConfigurationRequest(
bucket=args.bucket,
object_worm_configuration=config,
))
print(f'status code: {result.status_code},'
f' request id: {result.request_id},'
)
if __name__ == "__main__":
main()Go
package main
import (
"context"
"flag"
"log"
"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss"
"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials"
)
var (
region string
bucketName string
)
func init() {
flag.StringVar(®ion, "region", "", "The region in which the bucket is located.")
flag.StringVar(&bucketName, "bucket", "", "The name of the bucket.")
}
func main() {
flag.Parse()
if len(bucketName) == 0 {
flag.PrintDefaults()
log.Fatalf("invalid parameters, bucket name required")
}
if len(region) == 0 {
flag.PrintDefaults()
log.Fatalf("invalid parameters, region required")
}
cfg := oss.LoadDefaultConfig().
WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
WithRegion(region)
client := oss.NewClient(cfg)
request := &oss.PutBucketObjectWormConfigurationRequest{
Bucket: oss.Ptr(bucketName),
ObjectWormConfiguration: &oss.ObjectWormConfiguration{
ObjectWormEnabled: oss.Ptr("Enabled"),
Rule: &oss.ObjectWormRule{
DefaultRetention: &oss.ObjectWormDefaultRetention{
Mode: oss.Ptr("COMPLIANCE"),
Days: oss.Ptr(int32(1)),
},
},
},
}
result, err := client.PutBucketObjectWormConfiguration(context.TODO(), request)
if err != nil {
log.Fatalf("failed to put bucket object worm configuration %v", err)
}
log.Printf("put bucket object worm configuration result:%#v\n", result)
}Java
import com.aliyun.sdk.service.oss2.OSSClient;
import com.aliyun.sdk.service.oss2.OSSClientBuilder;
import com.aliyun.sdk.service.oss2.credentials.CredentialsProvider;
import com.aliyun.sdk.service.oss2.credentials.EnvironmentVariableCredentialsProvider;
import com.aliyun.sdk.service.oss2.models.*;
public class PutBucketObjectWormConfigurationDemo {
public static void main(String[] args) {
CredentialsProvider provider = new EnvironmentVariableCredentialsProvider();
OSSClient client = OSSClient.newBuilder()
.credentialsProvider(provider)
.region("cn-hangzhou")
.build();
try {
ObjectWormConfigurationDefaultRetention defaultRetention = ObjectWormConfigurationDefaultRetention.newBuilder()
.mode("COMPLIANCE")
.days(1)
.build();
ObjectWormConfigurationRule rule = ObjectWormConfigurationRule.newBuilder()
.defaultRetention(defaultRetention)
.build();
ObjectWormConfiguration objectWormConfiguration = ObjectWormConfiguration.newBuilder()
.objectWormEnabled("Enabled")
.rule(rule)
.build();
PutBucketObjectWormConfigurationRequest request = PutBucketObjectWormConfigurationRequest.newBuilder()
.bucket("examplebucket")
.objectWormConfiguration(objectWormConfiguration)
.build();
PutBucketObjectWormConfigurationResult result = client.putBucketObjectWormConfiguration(request);
System.out.printf("Status code:%d, request id:%s%n",
result.statusCode(), result.requestId());
} catch (Exception e) {
System.out.printf("error: %s%n", e);
} finally {
client.close();
}
}
}API
調用PutBucketObjectWormConfiguration介面開啟Object Worm,請求體樣本如下。以下樣本為Bucket開啟ObjectWorm並設定預設保留原則為合規模式保留1天。
PUT /?objectWorm HTTP/1.1
Date: Thu, 17 Mar 2026 11:18:32 GMT
Content-Length: 188
Content-Type: application/xml
Content-MD5: B2M2Y8AsgTpgAmY7PhC****
Host: examplebucket.oss-cn-hangzhou.aliyuncs.com
Authorization: OSS4-HMAC-SHA256 Credential=LTAI********************/20260317/cn-hangzhou/oss/aliyun_v4_request,AdditionalHeaders=content-length,Signature=a7c3554c729d****
<?xml version="1.0" encoding="UTF-8"?>
<ObjectWormConfiguration>
<ObjectWormEnabled>Enabled</ObjectWormEnabled>
<Rule>
<DefaultRetention>
<Mode>COMPLIANCE</Mode>
<Days>1</Days>
</DefaultRetention>
</Rule>
</ObjectWormConfiguration>為Object配置保留原則
為指定Object版本配置獨立的保留原則,包括保留模式和保留時間。Object層級的策略優先順序高於Bucket預設保留原則。
控制台
支援在檔案清單頁或檔案詳情頁為已上傳的Object配置保留原則。
登入OSS管理主控台。
在左側導覽列,單擊Bucket列表,然後單擊目標Bucket名稱。
在左側導覽列,單擊檔案管理,找到目標檔案。
單擊目標檔案右側的。
在彈出的設定面板中,配置預設保留模式和保留時間,然後單擊確定。
合規模式下,已設定保留原則的Object僅支援延長保留時間,不支援縮短。
ossutil
為儲存空間examplebucket中的對象exampleobject配置合規模式保留原則,保留到期日為2026-12-31T00:00:00.000Z。
使用XML設定檔,retention.xml內容如下:
<?xml version="1.0" encoding="UTF-8"?>
<Retention>
<Mode>COMPLIANCE</Mode>
<RetainUntilDate>2026-12-31T00:00:00.000Z</RetainUntilDate>
</Retention>命令樣本如下:
ossutil api put-object-retention --bucket examplebucket --key exampleobject --retention file://retention.xmlSDK
以下程式碼範例示範如何通過SDK為Object配置保留原則。
Python
import argparse
import alibabacloud_oss_v2 as oss
from datetime import datetime, timedelta, timezone
parser = argparse.ArgumentParser(description="put object retention sample")
parser.add_argument('--region', help='The region in which the bucket is located.', required=True)
parser.add_argument('--bucket', help='The name of the bucket.', required=True)
parser.add_argument('--endpoint', help='The domain names that other services can use to access OSS')
parser.add_argument('--key', help='The name of the object.', required=True)
def main():
args = parser.parse_args()
# Loading credentials values from the environment variables
credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()
# Using the SDK's default configuration
cfg = oss.config.load_default()
cfg.credentials_provider = credentials_provider
cfg.region = args.region
if args.endpoint is not None:
cfg.endpoint = args.endpoint
client = oss.Client(cfg)
# Calculate retain until date (1 days from now) in ISO 8601 format
# Use UTC time (recommended for OSS)
retain_until_date = datetime.now(timezone.utc) + timedelta(days=1)
retain_until_iso = retain_until_date.strftime('%Y-%m-%dT%H:%M:%S.000Z')
# Create retention configuration
retention_config = oss.Retention(
mode=oss.ObjectRetentionModeType.COMPLIANCE,
retain_until_date=retain_until_iso,
)
# Set object retention
result = client.put_object_retention(oss.PutObjectRetentionRequest(
bucket=args.bucket,
key=args.key,
retention=retention_config,
))
print(f'status code: {result.status_code},'
f' request id: {result.request_id}')
if __name__ == "__main__":
main()Go
package main
import (
"context"
"flag"
"log"
"time"
"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss"
"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials"
)
var (
region string
bucketName string
objectName string
)
func init() {
flag.StringVar(®ion, "region", "", "The region in which the bucket is located.")
flag.StringVar(&bucketName, "bucket", "", "The name of the bucket.")
flag.StringVar(&objectName, "object", "", "The name of the object.")
}
func main() {
flag.Parse()
if len(region) == 0 {
flag.PrintDefaults()
log.Fatalf("invalid parameters, region required")
}
if len(bucketName) == 0 {
flag.PrintDefaults()
log.Fatalf("invalid parameters, bucket name required")
}
if len(objectName) == 0 {
flag.PrintDefaults()
log.Fatalf("invalid parameters, object name required")
}
cfg := oss.LoadDefaultConfig().
WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
WithRegion(region)
client := oss.NewClient(cfg)
date := time.Now().UTC().Add(5 * time.Hour).Format("2006-01-02T15:04:05.000Z")
putRequest := &oss.PutObjectRetentionRequest{
Bucket: oss.Ptr(bucketName),
Key: oss.Ptr(objectName),
Retention: &oss.ObjectWormRetention{
Mode: oss.Ptr("COMPLIANCE"),
RetainUntilDate: oss.Ptr(date),
},
}
putResult, err := client.PutObjectRetention(context.TODO(), putRequest)
if err != nil {
log.Fatalf("failed to put object retention %v", err)
}
log.Printf("put object retention result:%#v\n", putResult)
}Java
import com.aliyun.sdk.service.oss2.OSSClient;
import com.aliyun.sdk.service.oss2.OSSClientBuilder;
import com.aliyun.sdk.service.oss2.credentials.CredentialsProvider;
import com.aliyun.sdk.service.oss2.credentials.EnvironmentVariableCredentialsProvider;
import com.aliyun.sdk.service.oss2.models.*;
public class PutObjectRetentionDemo {
public static void main(String[] args) {
CredentialsProvider provider = new EnvironmentVariableCredentialsProvider();
OSSClient client = OSSClient.newBuilder()
.credentialsProvider(provider)
.region("cn-hangzhou")
.build();
try {
Retention retention = Retention.newBuilder()
.mode("COMPLIANCE")
.retainUntilDate("2026-12-31T00:00:00.000Z")
.build();
PutObjectRetentionRequest request = PutObjectRetentionRequest.newBuilder()
.bucket("examplebucket")
.key("exampleobject")
.retention(retention)
.build();
PutObjectRetentionResult result = client.putObjectRetention(request);
System.out.printf("Status code:%d, request id:%s%n",
result.statusCode(), result.requestId());
} catch (Exception e) {
System.out.printf("error: %s%n", e);
} finally {
client.close();
}
}
}API
調用PutObjectRetention介面為Object配置保留原則,請求體樣本如下。
PUT /exampleobject?retention&versionId=CAEQNhiBgMDJgZCA0BYiIDc4MGZj**** HTTP/1.1
Date: Thu, 17 Mar 2026 11:18:32 GMT
Content-MD5: B2M2Y8AsgTpgAmY7PhC****
Content-Type: application/xml
Content-Length: 162
Host: examplebucket.oss-cn-hangzhou.aliyuncs.com
Authorization: OSS4-HMAC-SHA256 Credential=LTAI********************/20260317/cn-hangzhou/oss/aliyun_v4_request,Signature=****
<Retention>
<Mode>COMPLIANCE</Mode>
<RetainUntilDate>2026-10-11T00:00:00.000Z</RetainUntilDate>
</Retention>上傳時配置保留原則
上傳Object時可通過要求標頭直接配置保留原則,無需單獨調用PutObjectRetention介面。支援PutObject、PutObject和InitiateMultipartUpload操作。
控制台
登入OSS管理主控台,進入目標Bucket的檔案管理頁面。
單擊上傳檔案。
在上傳面板中展開進階選項,找到預設保留原則設定項。
選擇單獨設定,配置保留模式和保留時間,然後上傳檔案。
說明若選擇繼承Bucket預設策略,則上傳的檔案將自動應用Bucket的預設保留原則。
ossutil
通過ossutil的 API級命令put-object上傳檔案時,使用--object-worm-mode和--object-worm-retain-until-date參數指定保留原則。
ossutil api put-object --bucket examplebucket --key exampleobject --body file://localfile.txt --object-worm-mode COMPLIANCE --object-worm-retain-until-date 2026-10-11T00:00:00.000ZSDK
以下程式碼範例示範如何在調用PutObject介面上傳檔案時配置保留原則。
import alibabacloud_oss_v2 as oss
credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()
cfg = oss.config.load_default()
cfg.credentials_provider = credentials_provider
cfg.region = 'cn-hangzhou'
client = oss.Client(cfg)
# 上傳檔案並設定保留原則:合規模式,保留至2026年10月11日
result = client.put_object(oss.PutObjectRequest(
bucket='examplebucket',
key='exampleobject',
body='Hello OSS',
object_worm_mode='COMPLIANCE',
object_worm_retain_until_date='2026-10-11T00:00:00.000Z',
))
print(f'status code: {result.status_code}')import com.aliyun.sdk.service.oss2.OSSClient;
import com.aliyun.sdk.service.oss2.credentials.EnvironmentVariableCredentialsProvider;
import com.aliyun.sdk.service.oss2.models.*;
import com.aliyun.sdk.service.oss2.transport.BinaryData;
public class UploadWithRetention {
public static void main(String[] args) {
OSSClient client = OSSClient.newBuilder()
.credentialsProvider(new EnvironmentVariableCredentialsProvider())
.region("cn-hangzhou")
.build();
try {
// 上傳檔案並設定保留原則:合規模式,保留至2026年10月11日
PutObjectResult result = client.putObject(PutObjectRequest.newBuilder()
.bucket("examplebucket")
.key("exampleobject")
.body(BinaryData.fromString("Hello OSS"))
.header("x-oss-object-worm-mode", "COMPLIANCE")
.header("x-oss-object-worm-retain-until-date", "2026-10-11T00:00:00.000Z")
.build());
System.out.printf("status code: %d%n", result.statusCode());
} finally {
client.close();
}
}
}package main
import (
"context"
"fmt"
"strings"
"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss"
"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials"
)
func main() {
cfg := oss.LoadDefaultConfig().
WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
WithRegion("cn-hangzhou")
client := oss.NewClient(cfg)
// 上傳檔案並設定保留原則:合規模式,保留至2026年10月11日
request := &oss.PutObjectRequest{
Bucket: oss.Ptr("examplebucket"),
Key: oss.Ptr("exampleobject"),
Body: strings.NewReader("Hello OSS"),
ObjectWormMode: oss.Ptr("COMPLIANCE"),
ObjectWormRetainUntilDate: oss.Ptr("2026-10-11T00:00:00.000Z"),
}
_, err := client.PutObject(context.TODO(), request)
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println("Object uploaded with retention successfully")
}API
調用PutObject介面上傳檔案時,通過要求標頭配置保留原則。
PUT /exampleobject HTTP/1.1
Host: examplebucket.oss-cn-hangzhou.aliyuncs.com
x-oss-object-worm-mode: COMPLIANCE
x-oss-object-worm-retain-until-date: 2026-10-11T00:00:00.000Z
Content-MD5: B2M2Y8AsgTpgAmY7PhC****
Authorization: SignatureValue
[Object Content]注意事項
不可關閉:一旦為Bucket開啟Object Worm,將無法關閉該功能,除非登出阿里雲帳號。請在開啟前充分評估業務需求。
預設策略生效範圍:預設保留原則僅對後續新上傳的檔案生效,存量檔案不會自動生效。如需對存量Object設定保留原則,需通過PutObjectRetention介面單獨設定。
Object策略優先順序:如果Object設定了獨立的保留原則,則以Object層級的策略為準,優先順序高於Bucket預設保留原則。
保留期限只能延長:在合規模式下,已設定的保留到期日(RetainUntilDate)只能延長,不能縮短。
刪除檔案:處於ObjectWorm保留期內的檔案無法刪除。
DeleteMarker:刪除標記(DeleteMarker)不受Object Worm保護,可以正常建立和清理。但處於保留期內的Object版本不允許被刪除。
分區檔案:分區上傳產生的分區檔案(Part)同樣不受 Object Worm 保護。
資料複製:資料複製不會自動複製源端的ObjectWorm保留原則設定。目的端Object遵循目的Bucket自身的ObjectWorm設定,需要單獨配置。
生命週期管理:開啟ObjectWorm後,生命週期規則中的儲存類型轉換(Transition)操作不受影響,但處於保留期內的檔案不會被生命週期規則自動刪除(Expiration)。
日誌轉存:不建議將記錄檔投遞到已開啟ObjectWorm的Bucket中,老舊記錄檔可能因處於保留期內而無法自動刪除,導致儲存費用持續增長。
Append上傳:配置了Bucket層級ObjectWorm預設保留原則後,不支援使用追加上傳方式,且AppendObject不支援設定ObjectWorm。
Object ACL:處於ObjectWorm保留期內的檔案無法設定Object ACL。