全部文档
当前文档

暂无内容

如果没有找到您期望的内容,请尝试其他搜索词

文档中心

归档/冷归档类型文件拷贝为标准存储类型文件实现方案

最近更新时间:2026-10-15 14:43:39

通用操作流程

  1. 解冻源对象:对归档/冷归档对象调用 RestoreObject进行解冻,并等待解冻完成。归档存储类型文件1-10 分钟解冻完成,冷归档 1-12 小时解冻完成。

  2. copy 并显式指定 STANDARD:解冻完成后,用 CopyObject 指定目标存储类型为 STANDARD。

  3. 验证:HeadObject 确认目标对象 x-kss-storage-class 为 STANDARD。


REST API

解冻(RestoreObject)

POST /{ObjectKey}?restore HTTP/1.1
Host: {BucketName}.{endpoint}
Date: {date}
Authorization: {SignatureValue}

<RestoreRequest>
  <Days>1</Days>            <!-- 归档 1~7;冷归档 1~365 -->
  <JobParameters>
    <Tier>Expedited</Tier>  <!-- 冷归档可选:Expedited/Standard/Bulk;归档不填 -->
  </JobParameters>
</RestoreRequest>

响应:202(首次受理)/ 200(已解冻完成)/ 409(解冻中重复调用)

RestoreObject接口具体描述参见Restore Object文档。

查询解冻状态(HeadObject)

HEAD /{ObjectKey} HTTP/1.1
Host: {BucketName}.{endpoint}

# 响应头示例:
# x-kss-restore: ongoing-request="false", expiry-date="Sun, 16 Apr 2026 08:12:33 GMT"

ongoing-request="true" 解冻中,"false" 已解冻。

HeadObject接口具体描述参见HEAD Object文档。

copy 指定 STANDARD(CopyObject)

PUT /{DestinationKey} HTTP/1.1
Host: {DestinationBucket}.{endpoint}
x-kss-copy-source: /{SourceBucket}/{SourceKey}
x-kss-storage-class: STANDARD       <!-- 关键:显式指定标准存储 -->
x-kss-metadata-directive: COPY

PUT Object Copy默认行为分两种情况:源与目标 Key 相同时,继承源文件的存储类型;源和目标不同 Key 时,继承目标桶的存储类型。接口具体描述参见PUT Object Copy文档。

验证

HeadObject 目标对象,若x-kss-storage-class: STANDARD,则目标对象成功设置存储类型为标准存储。


KS3Util 命令行

# 1. 解冻源对象
# 归档:--days 取 1~7;冷归档:--days 取 1~365,--tier 可选 Expedited/Standard/Bulk(默认高优先级)
./ks3util restore ks3://srcBucket/srcKey --days 1

# 2. 复制并显式指定标准存储
./ks3util cp ks3://srcBucket/srcKey ks3://dstBucket/dstKey --storage-class STANDARD

# 3. 验证目标存储类型
./ks3util stat ks3://dstBucket/dstKey

使用该功能时,请确保KS3Util工具为 2.18.0 或更高版本。若未指定--storage-class参数,则复制后文件的存储类型与源文件保持一致。

--storage-class 可选值:STANDARD、STANDARD_IA、ARCHIVE。

KS3Util命令行工具具体描述可参考文档:解冻文件(restore)、复制文件(cp)。


Java SDK

解冻源对象

/**
     * 解冻对象
     * 仅归档及更冷存储类型的对象支持解冻操作
     */
    public void restoreObject() {
        // 初始化 Ks3Client,参见“初始化”文档
        Ks3Client ks3Client = initKs3Client();

        try {
            // 创建 RestoreObjectRequest 对象
            RestoreObjectRequest request = new RestoreObjectRequest("bucketName", "objectKey");
            // 设置解冻时间,单位:天
            // 可设置解冻状态持续时间,归档范围为1-7天,冷归档范围为1-365天。
            // 对于已处于解冻状态中的文件,可再次进行解冻操作,重新设置解冻持续时间,新设置的解冻持续时间将以当天为起始时间重新开始计算。
            request.setExpirationInDays(1);
            // 设置解冻优先级,取值:Expedited 高优先级、Standard 标准、Bulk 批量
            // 如果对象存储类型是 ColdArchive 冷归档,则可选 3 种,默认为 Expedited 高优先级
            // 如果对象存储类型是 Archive 归档则不支持设置解冻优先级
            request.setTier(RestoreTier.EXPEDITED);
            // 解冻对象
            RestoreObjectResult restoreObjectResult = ks3Client.restoreObject(request);
            // 获取对象存储类型:Archive 归档、ColdArchive 冷归档
            System.out.println("Storage Class: " + restoreObjectResult.getStorageClass());
            // 获取解冻状态,取值:RESTORE:解冻,RESTORING:解冻中,RESTORED:已解冻
            // 如果是初次解冻,一般不会立即完成,可以稍后使用 headObject 接口获取解冻状态
            System.out.println("RestoreStatus: " + restoreObjectResult.getType());
        } catch (Ks3ServiceException e) {
            System.out.println("Ks3ServiceException occurred, which means the request was made to KS3, but KS3 returned an error response for some reason.");
            System.out.println("Error Message: " + e.getErrorMessage());
            System.out.println("Error Code: " + e.getErrorCode());
            System.out.println("Request ID: " + e.getRequestId());
        } catch (Ks3ClientException e) {
            System.out.println("Ks3ClientException occurred, which means the client encountered an internal error while trying to communicate with KS3.");
            System.out.println("Error Message: " + e.getMessage());
        } finally {
            // 不再使用时,关闭 Ks3Client
            ks3Client.shutdown();
        }
    }

查询解冻状态

/**
     * 获取对象解冻状态
     */
    public void getObjectRestoreStatus() {
        // 初始化 Ks3Client,参见“初始化”文档
        Ks3Client ks3Client = initKs3Client();

        try {
            // 获取对象解冻状态
            HeadObjectResult headObjectResult = ks3Client.headObject("bucketName", "objectKey");
            // 对解冻中的或已解冻的归档文件进行head请求时,会返回x-kss-restore响应头
            // 解冻中的文件会返回x-kss-restore: ongoing-request="true"
            // 已解冻的文件会返回x-kss-restore: ongoing-request="false"及解冻过期时间,
            // 例如:x-kss-restore: ongoing-request="false", expiry-date="Sun, 16 Apr 2017 08:12:33 GMT"
            String restoreHeaderValue = (String) headObjectResult.getObjectMetadata().getMeta(HttpHeaders.XKssRestore.toString());
            System.out.println("RestoreStatus: " + restoreHeaderValue);
            // 可以使用以下方法获取解冻状态
            RestoreStatus restoreStatus = headObjectResult.getObjectMetadata().getRestoreStatus();
            if (restoreStatus != null) {
                System.out.println("Ongoing: " + restoreStatus.isOngoing());
                System.out.println("Expiry Date: " + restoreStatus.getExpiryDate());
            }
        } catch (Ks3ServiceException e) {
            System.out.println("Ks3ServiceException occurred, which means the request was made to KS3, but KS3 returned an error response for some reason.");
            System.out.println("Error Message: " + e.getErrorMessage());
            System.out.println("Error Code: " + e.getErrorCode());
            System.out.println("Request ID: " + e.getRequestId());
        } catch (Ks3ClientException e) {
            System.out.println("Ks3ClientException occurred, which means the client encountered an internal error while trying to communicate with KS3.");
            System.out.println("Error Message: " + e.getMessage());
        } finally {
            // 不再使用时,关闭 Ks3Client
            ks3Client.shutdown();
        }
    }

copy 并显式指定标准存储

// 初始化 Ks3Client,参见“初始化”文档
        Ks3Client ks3Client = initKs3Client();

        try {
            // 创建copy请求,将sourceBucket这个存储空间下的sourceKey这个object复制到destinationBucket这个存储空间下,并命名为destinationObject
            CopyObjectRequest request = new CopyObjectRequest("destinationBucket", "destinationObject", "sourceBucket", "sourceKey");

            // 设置新文件的ACL
            request.setCannedAcl(CannedAccessControlList.Private);
            // 或者指定用户的权限
            AccessControlList acl = new AccessControlList();
            acl.addGrant(new GranteeId("<user-id-1>"), Permission.Read);
            acl.addGrant(new GranteeId("<user-id-2>"), Permission.Write);
            request.setAccessControlList(acl);

            // 设置新文件的存储类型
            request.setStorageClass(StorageClass.Standard);

            // 设置新文件的元数据
            ObjectMetadata objectMetadata = new ObjectMetadata();
            objectMetadata.setContentType("text/plain");
            objectMetadata.setUserMeta("key1", "value1");
            // 设置新文件的元数据指令,REPLACE 表示替换,COPY 表示保留原有元数据
            objectMetadata.setHeader(HttpHeaders.XKssMetadataDirective.toString(), "REPLACE");
            // 设置新文件的标签指令,REPLACE 表示替换,COPY 表示保留原有标签
            objectMetadata.setHeader(HttpHeaders.XKssTaggingDirective.toString(), "REPLACE");
            request.setNewObjectMetadata(objectMetadata);

            // 设置新文件的标签
            ObjectTagging objectTagging = new ObjectTagging();
            objectTagging.addObjectTag("key1", "value1");
            request.setObjectTagging(objectTagging);

            // 如果目的文件已存在,是否覆盖,true:不覆盖,false:覆盖
            request.setForbidOverwrite(true);

            ks3Client.copyObject(request);
        } catch (Ks3ServiceException e) {
            System.out.println("Ks3ServiceException occurred, which means the request was made to KS3, but KS3 returned an error response for some reason.");
            System.out.println("Error Message: " + e.getErrorMessage());
            System.out.println("Error Code: " + e.getErrorCode());
            System.out.println("Request ID: " + e.getRequestId());
        } catch (Ks3ClientException e) {
            System.out.println("Ks3ClientException occurred, which means the client encountered an internal error while trying to communicate with KS3.");
            System.out.println("Error Message: " + e.getMessage());
        } finally {
            // 不再使用时,关闭 Ks3Client
            ks3Client.shutdown();
        }

Java SDK 在不指定 storage-class 时遵循服务端 CopyObject 默认行为,为避免复制结果仍为归档,务必显式指定 StorageClass.Standard。

SDK具体描述可参考文档:解冻归档文件(Java)、普通复制(Java)。


Python SDK

解冻源对象

from ks3.connection import Connection
from ks3.exception import S3ResponseError, KS3ClientError

conn = Connection('<yourAccessKeyId>', '<yourAccessKeySecret>', host='<YOUR_REGION_ENDPOINT>')
src_b = conn.get_bucket('srcBucket')

try:
    src_k = src_b.get_key('srcKey')
    # 归档:days 取 1~7(归档不支持 tier)
    src_k.restore_object(days=1)
    # 冷归档:days 取 1~365,tier 可选 Standard/Expedited/Bulk(仅冷归档支持,默认 Standard)
    # src_k.restore_object(days=1, tier='Expedited')
except S3ResponseError as e:
    print(f'服务端异常: status={e.status}, reason={e.reason}, request_id={e.request_id}')
except KS3ClientError as e:
    print(f'客户端异常: {e}')

查询解冻状态

src_k = src_b.get_key('srcKey', validate=True)
# src_k.ongoing_restore 为 True 表示解冻中;为 False 且 expiry_date 有值表示已解冻
print(f'解冻中: {src_k.ongoing_restore}, 过期时间: {src_k.expiry_date}')

copy 并显式指定标准存储

# 通过 headers 传 x-kss-storage-class
ret = dst_b.copy_key('dstKey', 'srcBucket', 'srcKey',
                     headers={'x-kss-storage-class': 'STANDARD'})

验证

dst_b = conn.get_bucket('dstBucket')
dst_k = dst_b.get_key('dstKey', validate=True)
print(f'目标对象存储类型: {dst_k.storage_class}')

Python SDK 指定目标存储类型的方式:在 copy_key 中通过 headers={'x-kss-storage-class': 'STANDARD'} 传入。不指定时默认跟随目标桶存储类型。

SDK具体描述可参考文档:解冻归档文件(Python)、复制文件(Python)。


Go SDK

解冻源对象

package main

import (
    "fmt"
    "github.com/ks3sdklib/aws-sdk-go/aws"
    "github.com/ks3sdklib/aws-sdk-go/aws/awsutil"
    "github.com/ks3sdklib/aws-sdk-go/aws/credentials"
    "github.com/ks3sdklib/aws-sdk-go/service/s3"
)

func main() {
    // 创建访问凭证,请将<AccessKeyID>与<SecretAccessKey>替换为实际值
    cre := credentials.NewStaticCredentials("<AccessKeyID>", "<SecretAccessKey>", "")
    // 创建KS3客户端,更多配置项请查看初始化文档
    client := s3.New(&aws.Config{
        Credentials: cre,                          // 访问凭证
        Region:      "BEIJING",                    // 访问地域
        Endpoint:    "ks3-cn-beijing.ksyuncs.com", // 访问域名
    })
    // 解冻归档文件
    resp, err := client.RestoreObject(&s3.RestoreObjectInput{
        Bucket: aws.String("srcBucket"), // 存储空间名称,必填
        Key:    aws.String("srcKey"),    // 对象的key,必填
        RestoreRequest: &s3.RestoreRequest{
            Days: aws.Long(1), // 设置解冻天数,归档范围为1-7天,冷归档范围为1-365天,非必填
            //JobParameters: &s3.JobParameters{
            //    Tier: aws.String(s3.RestoreTierExpedited), // 设置解冻优先级,取值:Expedited 高优先级、Standard 标准、Bulk 批量,非必填
            //},
        },
    })
    if err != nil {
        panic(err)
    }
    fmt.Println("结果:\n", awsutil.StringValue(resp))
}

查询解冻状态

    // 获取文件元数据信息
    resp, err := client.HeadObject(&s3.HeadObjectInput{
        Bucket: aws.String("srcBucket"), // 存储空间名称,必填
        Key:    aws.String("srcKey"),    // 对象的key,必填
    })
    if err != nil {
        panic(err)
    }
    // 对解冻中的或已解冻的归档文件进行head请求时,会返回 X-Amz-Restore 响应头
    // 解冻中的文件会返回 X-Amz-Restore: ongoing-request="true"
    // 已解冻的文件会返回 X-Amz-Restore: ongoing-request="false"及解冻过期时间,
    // 例如:X-Amz-Restore: ongoing-request="false", expiry-date="Sun, 16 Apr 2017 08:12:33 GMT"
    fmt.Println("结果:\n", awsutil.StringValue(resp))

copy 并显式指定标准存储

    // 高级复制
    resp, err := client.CopyFile(&s3.CopyFileInput{
        SourceBucket: aws.String("srcBucket"),             // 源存储空间名称,必填
        SourceKey:    aws.String("srcKey"),                // 源对象的key,必填
        Bucket:       aws.String("dstBucket"),             // 目标存储空间名称,必填
        Key:          aws.String("dstKey"),                // 目标对象的key,必填
        StorageClass: aws.String(s3.StorageClassStandard), // 复制后文件的存储类型,必填
    })
    if err != nil {
        panic(err)
    }
    fmt.Println("结果:\n", awsutil.StringValue(resp))

验证

    // 获取文件元数据信息
    resp, err := client.HeadObject(&s3.HeadObjectInput{
        Bucket: aws.String("dstBucket"), // 存储空间名称,必填
        Key:    aws.String("dstKey"),    // 对象的key,必填
    })
    if err != nil {
        panic(err)
    }
    fmt.Println("结果:\n", awsutil.StringValue(resp))

Go SDK 拷贝在不指定 StorageClass 时存储类型与源对象一致。

SDK具体描述可参考文档:解冻归档文件(Go)、高级复制。

文档导读
纯净模式常规模式

纯净模式

点击可全屏预览文档内容
文档反馈