对象级别保留策略(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。