开启版本控制下Object的操作

重要

本文中含有需要您注意的重要提示信息,忽略该信息可能对您的业务造成影响,请务必仔细阅读。

存储空间(Bucket)开启版本控制后,OSS会为Bucket中所有文件(Object)的每个版本指定唯一的ID值,且Bucket中现有Object的内容和权限保持不变。开启版本控制后,还能够防止意外覆盖或者删除Object ,并允许查询和恢复Object的历史版本。

注意事项

在已开启版本控制的Bucket中进行上传、列举、下载、删除、恢复文件等操作时:

  • OSS会维护一个当前版本Object以及零个或多个历史版本Object。

  • 如果在Bucket开启版本控制前上传了Object,则OSSObject的版本ID值置为null。

  • 本文图示中的版本ID均以简短版本ID代替。

更多信息,请参见版本控制介绍

上传文件

在已开启版本控制的Bucket中上传Object时,OSS会为这些上传的Object自动添加唯一的版本ID。

说明

PutObject、PostObject、CopyObject 、MultipartUpload等操作都会为新生成的Object自动添加唯一的版本ID。

通过PUT操作上传Object时,OSS会为该Object指定唯一的版本号(ID=111111)。

通过PUT操作第一次上传同名Object(key=example.jpg)时,原始Object版本(ID=111111)作为历史版本,生成的新版本(ID=222222)将作为当前版本保存在Bucket中。当再次上传同名Object时,原始Object版本(包括ID=111111以及ID=222222)将作为历史版本,而生成的新版本(ID=333333)则作为当前版本保存在Bucket中。

使用OSS控制台

  1. 登录OSS管理控制台

  2. 单击Bucket 列表,然后单击目标Bucket名称。

  3. 在左侧导航栏,选择文件管理>文件列表

  4. 文件列表页面,单击上传文件

  5. 上传文件面板,按如下说明配置各项参数。

    1. 设置基础选项。

      参数

      说明

      上传到

      设置文件上传到目标Bucket后的存储路径。

      • 当前目录:将文件上传到当前目录。

      • 指定目录:将文件上传到指定目录,您需要输入目录名称。如果输入的目录不存在,OSS将自动创建对应的文件目录并将文件上传到该目录中。

        目录命名规范如下:

        • 请使用符合要求的UTF-8字符;长度必须在1~254字符之间。

        • 不允许以正斜线(/)或反斜线(\)开头。

        • 不允许出现连续的正斜线(/)。

        • 不允许出现名为 .. 的目录。

      文件ACL

      设置文件读写权限ACL。

      • 继承Bucket:以Bucket读写权限为准。

      • 私有(推荐):只有文件Owner拥有该文件的读写权限,其他用户没有权限操作该文件。

      • 公共读:文件Owner拥有该文件的读写权限,其他用户(包括匿名访问者)都可以对文件进行访问,这有可能造成您数据的外泄以及费用激增,请谨慎操作。

      • 公共读写:任何用户(包括匿名访问者)都可以对文件进行访问,并且向该文件写入数据。这有可能造成您数据的外泄以及费用激增。如果被人恶意写入违法信息还可能会侵害您的合法权益。除特殊场景外,不建议您为文件配置公共读写权限。

      关于文件ACL的更多信息,请参见设置Object ACL

      待上传文件

      选择您需要上传的文件或文件夹。

      您可以单击扫描文件扫描文件夹选择本地文件或文件夹,或者直接拖拽目标文件或文件夹到待上传文件区域。

      如果上传文件夹中包含了无需上传的文件,请单击目标文件操作列的移除将其移出文件列表。

      重要
      • 在未开启版本控制的Bucket中上传文件时,如果上传的文件与已有文件同名,则覆盖已有文件。

      • 在已开启版本控制的Bucket中上传文件时,如果上传的文件与已有文件同名,则上传的文件将成为最新版本,已有文件将成为历史版本。

    2. 可选:单击高级选项右侧的image.png图标,设置文件存储类型、加密方式等高级选项。

      参数

      说明

      存储类型

      设置文件存储类型。 取值范围如下:

      • 继承Bucket(默认):以Bucket存储类型为准。

      • 标准存储提供高可靠、高可用、高性能的对象存储服务,能够支持频繁的数据访问。适用于各种社交、分享类的图片、音视频应用、大型网站、大数据分析等业务场景。标准存储类型支持同城冗余ZRS(Zone-redundant storage)和本地冗余LRS(Locally redundant storage)两种数据冗余存储方式。

      • 低频访问存储提供高持久性、较低存储成本的对象存储服务。有最小计量单位(64 KB)和最低存储时间(30天)的要求。支持数据实时访问,访问数据时会产生数据取回费用,适用于较低访问频率(平均每月访问频率12次)的业务场景。低频访问存储支持同城冗余和本地冗余两种数据冗余存储方式。

      • 归档存储提供高持久性、极低存储成本的对象存储服务。有最小计量单位(64 KB)和最低存储时间(60天)要求。归档存储数据支持解冻(约1分钟)后访问或直接访问。解冻后访问会产生归档存储数据取回容量费用,直接访问会产生归档直读数据取回容量费用。归档存储适用于数据长期保存的业务场景,例如档案数据、医疗影像、科学资料、影视素材等。归档存储支持同城冗余和本地冗余两种数据冗余存储方式。

      • 冷归档存储提供高持久性、比归档存储的存储成本更低的对象存储服务。有最小计量单位(64 KB)和最低存储时间(180天)的要求。数据需解冻后访问,解冻时间根据数据大小和选择的解冻模式决定,解冻会产生数据取回费用以及取回请求费用。适用于需要超长时间存放的冷数据,例如因合规要求需要长期留存的数据、大数据及人工智能领域长期积累的原始数据、影视行业长期留存的媒体资源、在线教育行业的归档视频等业务场景。冷归档仅支持本地冗余的数据冗余存储方式。

      • 深度冷归档存储提供高持久性、比冷归档存储成本更低的对象存储服务。有最小计量单位(64 KB)和最低存储时间(180天)的要求。数据需解冻后访问,解冻时间根据数据大小和选择的解冻模式决定,解冻会产生数据取回费用以及取回请求费用。适用于需要超长时间存放的极冷数据,例如大数据及人工智能领域的原始数据的长期积累留存、媒体数据的长期保留、法规和合规性存档、磁带替换等业务场景。深度冷归档仅支持本地冗余的数据冗余存储方式。

      更多信息,请参见存储类型介绍

      服务端加密方式

      设置文件的服务端加密方式。 取值范围如下:

      • 继承 Bucket(默认):以Bucket的服务器端加密方式为准。

      • OSS完全托管:使用OSS托管的密钥进行加密。OSS会为每个Object使用不同的密钥进行加密,作为额外的保护,OSS会使用主密钥对加密密钥本身进行加密。

      • KMS:使用KMS默认托管的CMK或指定CMK ID进行加解密操作。

        使用KMS加密方式前,需要开通KMS服务。具体操作,请参见开通密钥管理服务

        KMS对应的加密密钥说明如下:

        加密密钥格式为<alias>(CMK ID)。其中<alias>为用户主密钥的别名,CMK ID为用户主密钥ID。取值范围如下:

        • alias/acs/oss(CMK ID):使用默认托管的CMK生成不同的密钥来加密不同的Object,并且在Object被下载时自动解密。

        • alias/<cmkname>(CMK ID):使用指定的CMK生成不同的密钥来加密不同的Object,并将加密ObjectCMK ID记录到Object的元数据中,具有解密权限的用户下载Object时会自动解密。其中<cmkname>为创建密钥时配置的主密钥可选标识。

          使用指定的CMK ID前,您需要在KMS管理控制台创建一个与Bucket处于相同地域的普通密钥或外部密钥。具体操作,请参见创建密钥

      • 加密算法可选择AES256SM4加密算法。

      用户自定义元数据

      用于为Object添加描述信息。您可以添加多条自定义元数据(User Meta),但所有的自定义元数据总大小不能超过8 KB。添加自定义元数据时,要求参数以x-oss-meta-为前缀,并为参数赋值,例如x-oss-meta-location:hangzhou

    3. 单击上传文件

      此时,您可以在任务列表面板的上传列表页签查看各个文件的上传进度。

使用阿里云SDK

以下仅列举常见SDK在已开启版本控制的Bucket中简单上传文件的代码示例。关于其他SDK简单上传的代码示例,请参见SDK简介

import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.common.comm.SignVersion;
import com.aliyun.oss.model.*;
import java.io.ByteArrayInputStream;

public class Demo {
    public static void main(String[] args) throws Exception {
        // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
        String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
        // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        // 填写Bucket名称,例如examplebucket。
        String bucketName = "examplebucket";
        // 填写Object的完整路径。Object完整路径中不能包含Bucket名称。
        String objectName = "exampledir/object";
        // 填写Bucket所在地域。以华东1(杭州)为例,Region填写为cn-hangzhou。
        String region = "cn-hangzhou";

        // 创建OSSClient实例。
        // 当OSSClient实例不再使用时,调用shutdown方法以释放资源。
        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);        
        OSS ossClient = OSSClientBuilder.create()
        .endpoint(endpoint)
        .credentialsProvider(credentialsProvider)
        .clientConfiguration(clientBuilderConfiguration)
        .region(region)               
        .build();

        try {
            // 以上传字符串为例。
            String content = "Hello OSS";
            PutObjectResult result = ossClient.putObject(bucketName, objectName, new ByteArrayInputStream(content.getBytes()));
            // 查看此次上传Object的VersionId。
            System.out.println("result.versionid: " + result.getVersionId());
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }
}
const OSS = require('ali-oss');

const client = new OSS({
  // yourregion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
  region: 'yourregion',
  // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
  accessKeyId: process.env.OSS_ACCESS_KEY_ID,
  accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
  authorizationV4: true,
  // yourbucketname填写存储空间名称。
  bucket: 'yourbucketname'
});

async function put() {
  const result = await client.put('fileName', path.normalize('D:\\localpath\\examplefile.txt');
  console.log(result.res.headers['x-oss-version-id']); // 查看此次上传object的版本ID。
}
put();
using System.Text;
using Aliyun.OSS;
using Aliyun.OSS.Common;

// yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
var endpoint = "yourEndpoint";
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
var accessKeyId = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_ID");
var accessKeySecret = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_SECRET");
// 填写Bucket名称,例如examplebucket。
var bucketName = "examplebucket";
// 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。
var objectName = "exampleobject.txt";
var objectContent = "More than just cloud.";
// 填写Bucket所在地域对应的Region。以华东1(杭州)为例,Region填写为cn-hangzhou。
const string region = "cn-hangzhou";

// 创建ClientConfiguration实例,按照您的需要修改默认参数。
var conf = new ClientConfiguration();

// 设置v4签名。
conf.SignatureVersion = SignatureVersion.V4;

// 创建OssClient实例。
var client = new OssClient(endpoint, accessKeyId, accessKeySecret, conf);
client.SetRegion(region);
try
{
    byte[] binaryData = Encoding.ASCII.GetBytes(objectContent);
    MemoryStream requestContent = new MemoryStream(binaryData);
    // 上传文件。
    var result = client.PutObject(bucketName, objectName, requestContent);
    Console.WriteLine("Put object succeeded versionid : {0}", result.VersionId);
}
catch (Exception ex)
{
    Console.WriteLine("Put object failed, {0}", ex.Message);
}
#include <alibabacloud/oss/OssClient.h>
using namespace AlibabaCloud::OSS;

int main(void)
{
    /* 初始化OSS账号信息。*/
            
    /* yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。*/
    std::string Endpoint = "yourEndpoint";
    /* yourRegion填写Bucket所在地域对应的Region。以华东1(杭州)为例,Region填写为cn-hangzhou。*/
    std::string Region = "yourRegion";
    /* 填写Bucket名称,例如examplebucket。*/
    std::string BucketName = "examplebucket";
    /* 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。*/
    std::string ObjectName = "exampledir/exampleobject.txt";

    /* 初始化网络等资源。*/
    InitializeSdk();

    ClientConfiguration conf;
    conf.signatureVersion = SignatureVersionType::V4;
    /* 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。*/
    auto credentialsProvider = std::make_shared<EnvironmentVariableCredentialsProvider>();
    OssClient client(Endpoint, credentialsProvider, conf);
    client.SetRegion(Region);
    std::shared_ptr<std::iostream> content = std::make_shared<std::stringstream>();
    *content << "test cpp sdk";
    PutObjectRequest request(BucketName, ObjectName, content);

    /* 上传文件。*/
    auto outcome = client.PutObject(request);

    if (outcome.isSuccess()) {
        std::cout << "versionid:" << outcome.result().VersionId() << std::endl;
    }
    else {
        /* 异常处理。*/
        std::cout << "PutObject fail" <<
        ",code:" << outcome.error().Code() <<
        ",message:" << outcome.error().Message() <<
        ",requestId:" << outcome.error().RequestId() << std::endl;
        return -1;
    }

    /* 释放网络等资源。*/
    ShutdownSdk();
    return 0;
}
package main

import (
	"context"
	"flag"
	"log"
	"strings"

	"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 // 对象名称
)

// init函数用于初始化命令行参数
func init() {
	flag.StringVar(&region, "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()

	// 检查bucket名称是否为空
	if len(bucketName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, bucket name required")
	}

	// 检查region是否为空
	if len(region) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, region required")
	}

	// 检查object名称是否为空
	if len(objectName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, object name required")
	}

	// 定义要上传的内容
	content := "hi oss"

	// 加载默认配置并设置凭证提供者和区域
	cfg := oss.LoadDefaultConfig().
		WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
		WithRegion(region)

	// 创建OSS客户端
	client := oss.NewClient(cfg)

	// 创建上传对象的请求
	request := &oss.PutObjectRequest{
		Bucket: oss.Ptr(bucketName),        // 存储空间名称
		Key:    oss.Ptr(objectName),        // 对象名称
		Body:   strings.NewReader(content), // 要上传的内容
	}

	// 执行上传对象的请求
	result, err := client.PutObject(context.TODO(), request)
	if err != nil {
		log.Fatalf("failed to put object %v", err)
	}

	// 打印上传对象的versionId
	log.Printf("put object result versionId:%#v\n", *result.VersionId)
}
import argparse
import requests
import alibabacloud_oss_v2 as oss

# 创建命令行参数解析器
parser = argparse.ArgumentParser(description="put object sample")
# 添加命令行参数 --region,表示存储空间所在的区域,必需参数
parser.add_argument('--region', help='The region in which the bucket is located.', required=True)
# 添加命令行参数 --bucket,表示存储空间的名称,必需参数
parser.add_argument('--bucket', help='The name of the bucket.', required=True)
# 添加命令行参数 --endpoint,表示其他服务可用来访问OSS的域名,非必需参数
parser.add_argument('--endpoint', help='The domain names that other services can use to access OSS')
# 添加命令行参数 --key,表示对象的名称,必需参数
parser.add_argument('--key', help='The name of the object.', required=True)

def main():
    args = parser.parse_args()  # 解析命令行参数

    # 从环境变量中加载凭证信息,用于身份验证
    credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()

    # 加载SDK的默认配置,并设置凭证提供者
    cfg = oss.config.load_default()
    cfg.credentials_provider = credentials_provider
    # 设置配置中的区域信息
    cfg.region = args.region
    # 如果提供了endpoint参数,则设置配置中的endpoint
    if args.endpoint is not None:
        cfg.endpoint = args.endpoint

    # 使用配置好的信息创建OSS客户端
    client = oss.Client(cfg)

    # 上传本地文件
    local_file_path = '/yourLocalFilePath/yourFileName'
    with open(local_file_path, 'rb') as file:
        data = file.read()

    # 执行上传对象的请求,指定存储空间名称、对象名称和数据内容
    result = client.put_object(oss.PutObjectRequest(
        bucket=args.bucket,
        key=args.key,
        body=data,
    ))

    # 输出请求的结果状态码、请求ID、内容MD5、ETag、CRC64校验码和版本ID,用于检查请求是否成功
    print(f'status code: {result.status_code},'
          f' request id: {result.request_id},'
          f' content md5: {result.content_md5},'
          f' etag: {result.etag},'
          f' hash crc64: {result.hash_crc64},'
          f' version id: {result.version_id},'
    )

if __name__ == "__main__":
    main()  # 脚本入口,当文件被直接运行时调用main函数
<?php

// 引入自动加载文件 加载依赖库
require_once __DIR__ . '/../vendor/autoload.php';

use AlibabaCloud\Oss\V2 as Oss;

// 定义命令行参数描述
$optsdesc = [
    "region" => ['help' => 'The region in which the bucket is located', 'required' => True], // 区域是必填项 存储空间所在的区域
    "endpoint" => ['help' => 'The domain names that other services can use to access OSS', 'required' => False], // 终端节点是可选项 其他服务可以用来访问OSS的域名
    "bucket" => ['help' => 'The name of the bucket', 'required' => True], // 存储空间名称是必填项
    "key" => ['help' => 'The name of the object', 'required' => True], // 对象名称是必填项
];

// 生成长选项列表 用于解析命令行参数
$longopts = \array_map(function ($key) {
    return "$key:"; // 每个参数后面加冒号 表示需要值
}, array_keys($optsdesc));

// 解析命令行参数
$options = getopt("", $longopts);

// 检查必填参数是否缺失
foreach ($optsdesc as $key => $value) {
    if ($value['required'] === True && empty($options[$key])) {
        $help = $value['help'];
        echo "Error: the following arguments are required: --$key, $help"; // 提示用户缺少必填参数
        exit(1);
    }
}

// 获取命令行参数值
$region = $options["region"]; // 存储空间所在区域
$bucket = $options["bucket"]; // 存储空间名称
$key = $options["key"]; // 对象名称

// 使用环境变量加载凭证信息 AccessKeyId 和 AccessKeySecret
$credentialsProvider = new Oss\Credentials\EnvironmentVariableCredentialsProvider();

// 使用SDK的默认配置
$cfg = Oss\Config::loadDefault();

// 设置凭证提供者
$cfg->setCredentialsProvider($credentialsProvider);

// 设置区域
$cfg->setRegion($region);

// 如果提供了终端节点 则设置终端节点
if (isset($options["endpoint"])) {
    $cfg->setEndpoint($options["endpoint"]);
}

// 创建OSS客户端实例
$client = new Oss\Client($cfg);

// 定义要上传的数据内容
$data = 'Hello OSS';

// 创建上传对象的请求对象
$request = new Oss\Models\PutObjectRequest(
                bucket: $bucket,
                key: $key,
            );

// 设置请求体为数据流
$request->body = Oss\Utils::streamFor($data);

// 调用putObject方法上传对象
$result = $client->putObject($request);

// 打印返回结果
printf(
    'status code:' . $result->statusCode . PHP_EOL . // HTTP响应状态码
    'request id:' . $result->requestId . PHP_EOL . // 请求的唯一标识
    'etag:' . $result->etag . PHP_EOL // 对象的ETag值
);

使用命令行工具ossutil

关于使用ossutil在已开启版本控制的Bucket中简单上传文件的具体操作, 请参见cp(上传文件)

使用REST API

如果您的程序自定义要求较高,您可以直接发起REST API请求。直接发起REST API请求需要手动编写代码计算签名。更多信息,请参见PutObject

列举文件

在已开启版本控制的Bucket中,您可以使用GetBucketVersions(ListObjectVersions)接口获取Object的所有版本信息,包括删除标记。

  • GetBucket(ListObject)接口仅返回Object的当前版本,且当前版本不为删除标记。

  • 单个GetBucketVersions(ListObjectVersions)请求最多返回1000个版本Object。您可以通过发送多次请求来获取Object的所有版本。

    例如,如果Bucket中包含两个Key(如example.jpgphoto.jpg),且example.jpg900个版本,photo.jpg500个版本,则单个请求将按字母序和版本顺序列举example.jpg900个版本和photo.jpg100个版本。

如下图所示,在开启了版本控制的Bucket中,调用GetBucketVersions(ListObjectVersions)接口时,返回了Bucket中所有Object的所有版本,包含当前版本为删除标记的Object ;调用GetBucket(ListObject)接口时,则仅返回Object的当前版本,且当前版本不能为删除标记,因此仅返回当前版本ID444444Object。

使用OSS控制台

  1. 登录OSS管理控制台

  2. 单击Bucket 列表,然后单击目标Bucket名称。

    当前页面将分页显示该Bucket中所有Object的当前版本。如果需要查看包含删除标记在内的所有版本,请在文件列表页面单击历史版本右侧的显示

使用阿里云SDK

以下仅列举常见SDK在已开启版本控制的Bucket中列举文件的代码示例。关于其他SDK列举文件的代码示例,请参见SDK简介

import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.common.comm.SignVersion;
import com.aliyun.oss.model.*;

public class Demo {
    public static void main(String[] args) throws Exception {
        // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
        String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
        // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        // 填写Bucket名称,例如examplebucket。
        String bucketName = "examplebucket";
        // 填写Bucket所在地域。以华东1(杭州)为例,Region填写为cn-hangzhou。
        String region = "cn-hangzhou";

        // 创建OSSClient实例。
        // 当OSSClient实例不再使用时,调用shutdown方法以释放资源。
        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);        
        OSS ossClient = OSSClientBuilder.create()
        .endpoint(endpoint)
        .credentialsProvider(credentialsProvider)
        .clientConfiguration(clientBuilderConfiguration)
        .region(region)               
        .build();

        try {
            // 列举包括删除标记在内的所有Object的版本信息。
            String nextKeyMarker = null;
            String nextVersionMarker = null;
            VersionListing versionListing = null;
            do {
                ListVersionsRequest listVersionsRequest = new ListVersionsRequest()
                        .withBucketName(bucketName)
                        .withKeyMarker(nextKeyMarker)
                        .withVersionIdMarker(nextVersionMarker);

                versionListing = ossClient.listVersions(listVersionsRequest);
                for (OSSVersionSummary ossVersion : versionListing.getVersionSummaries()) {
                    System.out.println("key name: " + ossVersion.getKey());
                    System.out.println("versionid: " + ossVersion.getVersionId());
                    System.out.println("Is latest: " + ossVersion.isLatest());
                    System.out.println("Is delete marker: " + ossVersion.isDeleteMarker());
                }

                nextKeyMarker = versionListing.getNextKeyMarker();
                nextVersionMarker = versionListing.getNextVersionIdMarker();
            } while (versionListing.isTruncated());
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }
}
const OSS = require("ali-oss");

const client = new OSS({
  // yourregion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
  region: 'yourregion',
  // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
  accessKeyId: process.env.OSS_ACCESS_KEY_ID,
  accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
  authorizationV4: true,
  // 填写存储空间名称。
  bucket: 'yourbucketname'
});

// 列举包括删除标记在内的所有Object的版本信息。
async function getObjectVersions() {
  let nextKeyMarker = null;
  let nextVersionMarker = null;
  let versionListing = null;
  do {
    versionListing = await client.getBucketVersions({
      keyMarker: nextKeyMarker,
      versionIdMarker: nextVersionMarker,
    });

    versionListing.objects.forEach((o) => {
      console.log(`${o.name}, ${o.versionId}`);
    });
    versionListing.deleteMarker.forEach((o) => {
      console.log(`${o.name}, ${o.versionId}`);
    });

    nextKeyMarker = versionListing.NextKeyMarker;
    nextVersionMarker = versionListing.NextVersionIdMarker;
  } while (versionListing.isTruncated);
}

getObjectVersions();
import argparse
import alibabacloud_oss_v2 as oss

# 创建命令行参数解析器,并描述脚本用途:示例展示如何列出OSS存储空间中的对象版本
parser = argparse.ArgumentParser(description="list object versions sample")

# 添加命令行参数 --region,表示存储空间所在的区域,必需参数
parser.add_argument('--region', help='The region in which the bucket is located.', required=True)
# 添加命令行参数 --bucket,表示要操作的存储空间名称,必需参数
parser.add_argument('--bucket', help='The name of the bucket.', required=True)
# 添加命令行参数 --endpoint,表示其他服务可用来访问OSS的域名,非必需参数
parser.add_argument('--endpoint', help='The domain names that other services can use to access OSS')

def main():
    # 解析命令行提供的参数,获取用户输入的值
    args = parser.parse_args()

    # 从环境变量中加载访问OSS所需的认证信息,用于身份验证
    credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()

    # 使用SDK的默认配置创建配置对象,并设置认证提供者
    cfg = oss.config.load_default()
    cfg.credentials_provider = credentials_provider
    cfg.region = args.region

    # 如果提供了自定义endpoint,则更新配置对象中的endpoint属性
    if args.endpoint is not None:
        cfg.endpoint = args.endpoint

    # 使用上述配置初始化OSS客户端,准备与OSS交互
    client = oss.Client(cfg)

    # 创建用于分页列出对象版本的Paginator对象
    paginator = client.list_object_versions_paginator()

    # 遍历对象版本页面
    for page in paginator.iter_page(oss.ListObjectVersionsRequest(
            bucket=args.bucket,  # 存储空间名
        )
    ):
        # 遍历当前页面中的每个对象版本
        for o in page.version:
            # 打印每个对象版本的关键信息:
            # - key: 对象的键(名称)
            # - size: 对象的大小(字节数)
            # - version_id: 对象版本ID
            # - last_modified: 对象最后修改时间
            print(f'Object version: {o.key}, Size: {o.size}, Version_id: {o.version_id}, Last_modified: {o.last_modified}')


# 当此脚本被直接执行时,调用main函数开始处理逻辑
if __name__ == "__main__":
    main()  # 脚本入口点,控制程序流程从这里开始

使用命令行工具ossutil

关于在已开启版本控制的Bucket中列举文件的具体操作,请参见ls(列举账号级别下的资源)

使用REST API

如果您的程序自定义要求较高,您可以直接发起REST API请求。直接发起REST API请求需要手动编写代码计算签名。更多信息,请参见ListObjectVersions(GetBucketVersions)

下载文件

您可以在已开启版本控制的Bucket中下载当前版本或指定版本的Object。

通过GET请求下载Object时,未指定版本ID则返回当前版本(ID=333333)。

如果当前版本为删除标记(Delete Marker),在执行GET操作时,OSS会返回404 Not Found。

通过GET请求下载Object时,指定版本ID可获取特定版本(ID=222222)。

使用OSS控制台

  1. 登录OSS管理控制台

  2. 单击Bucket 列表,然后单击目标Bucket名称。

  3. 在左侧导航栏,选择文件管理>文件列表

  4. 文件列表页面,单击历史版本右侧的显示

  5. 单击指定版本的Object,在弹出的面板单击文件URL右侧的下载

使用阿里云SDK

以下仅列举常见SDK在已开启版本控制的Bucket中下载文件的代码示例。关于其他SDK下载文件的代码示例,请参见SDK简介

const OSS = require('ali-oss');

const client = new OSS({
  // yourregion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
  region: 'yourregion',
  // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
  accessKeyId: process.env.OSS_ACCESS_KEY_ID,
  accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
  authorizationV4: true,
  // yourbucketname填写存储空间名称。
  bucket: 'yourbucketname'
});

async function get() {
  // 文件名称。
  const result = await client.get('filename', {    
      // 查看下载文件的版本ID。
      versionId: 'versionid',
  });
  console.log(result.content);
}
get();
#include <alibabacloud/oss/OssClient.h>
using namespace AlibabaCloud::OSS;

int main(void)
{
    /* 初始化OSS账号信息。*/
            
    /* yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。*/
    std::string Endpoint = "yourEndpoint";
    /* yourRegion填写Bucket所在地域对应的Region。以华东1(杭州)为例,Region填写为cn-hangzhou。*/
    std::string Region = "yourRegion";
    /* 填写Bucket名称,例如examplebucket。*/
    std::string BucketName = "examplebucket";
    /* 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。*/
    std::string ObjectName = "exampledir/exampleobject.txt";

    /* 初始化网络等资源。*/
    InitializeSdk();

    ClientConfiguration conf;
    conf.signatureVersion = SignatureVersionType::V4;
    /* 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。*/
    auto credentialsProvider = std::make_shared<EnvironmentVariableCredentialsProvider>();
    OssClient client(Endpoint, credentialsProvider, conf);
    client.SetRegion(Region);

    /* 获取文件到本地内存。*/
    GetObjectRequest request(BucketName, ObjectName);
    request.setVersionId("yourObjectVersionId");
    auto outcome = client.GetObject(request);
    if (outcome.isSuccess()) {
        std::cout << "getObjectToBuffer" << " success, Content-Length:" << outcome.result().Metadata().ContentLength() << std::endl;
        /* 读取下载的Object内容。*/
        std::string content;
        *(outcome.result().Content()) >> content;
        std::cout << "getObjectToBuffer" << "content:" << content << std::endl;
        /* 查看本次下载Object的版本ID。*/
        std::cout << "versionid:" << outcome.result().VersionId() << std::endl;
    }
    else {
            /* 异常处理。*/
            std::cout << "getObjectToBuffer fail" <<
        ",code:" << outcome.error().Code() <<
        ",message:" << outcome.error().Message() <<
        ",requestId:" << outcome.error().RequestId() << std::endl;
        return -1;
    }

    /* 释放网络等资源。*/
    ShutdownSdk();
    return 0;
}
import argparse
import alibabacloud_oss_v2 as oss

# 创建命令行参数解析器
parser = argparse.ArgumentParser(description="get object sample")

# 添加命令行参数 --region,表示存储空间所在的区域,必需参数
parser.add_argument('--region', help='The region in which the bucket is located.', required=True)
# 添加命令行参数 --bucket,表示存储空间的名称,必需参数
parser.add_argument('--bucket', help='The name of the bucket.', required=True)
# 添加命令行参数 --endpoint,表示其他服务可用来访问OSS的域名,非必需参数
parser.add_argument('--endpoint', help='The domain names that other services can use to access OSS')
# 添加命令行参数 --key,表示对象的名称,必需参数
parser.add_argument('--key', help='The name of the object.', required=True)
# 添加命令行参数 --version_id,表示对象的版本ID,必需参数
parser.add_argument('--version_id', help='The version ID of the object.', required=True)

def main():
    # 解析命令行参数
    args = parser.parse_args()

    # 从环境变量中加载凭证信息,用于身份验证
    credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()

    # 加载SDK的默认配置,并设置凭证提供者
    cfg = oss.config.load_default()
    cfg.credentials_provider = credentials_provider

    # 设置配置中的区域信息
    cfg.region = args.region

    # 如果提供了endpoint参数,则设置配置中的endpoint
    if args.endpoint is not None:
        cfg.endpoint = args.endpoint

    # 使用配置好的信息创建OSS客户端
    client = oss.Client(cfg)

    # 执行获取对象的请求,指定存储空间名称和对象名称
    result = client.get_object(oss.GetObjectRequest(
        bucket=args.bucket,  # 指定存储空间名称
        key=args.key,  # 指定对象键名
        version_id=args.version_id, # 指定版本ID
    ))

    # 输出获取对象的结果信息,用于检查请求是否成功
    print(f'status code: {result.status_code},'
          f' request id: {result.request_id},'
          f' content length: {result.content_length},'
          f' content range: {result.content_range},'
          f' content type: {result.content_type},'
          f' etag: {result.etag},'
          f' last modified: {result.last_modified},'
          f' content md5: {result.content_md5},'
          f' cache control: {result.cache_control},'
          f' content disposition: {result.content_disposition},'
          f' content encoding: {result.content_encoding},'
          f' expires: {result.expires},'
          f' hash crc64: {result.hash_crc64},'
          f' storage class: {result.storage_class},'
          f' object type: {result.object_type},'
          f' version id: {result.version_id},'
          f' tagging count: {result.tagging_count},'
          f' server side encryption: {result.server_side_encryption},'
          f' server side data encryption: {result.server_side_data_encryption},'
          f' next append position: {result.next_append_position},'
          f' expiration: {result.expiration},'
          f' restore: {result.restore},'
          f' process status: {result.process_status},'
          f' delete marker: {result.delete_marker},'
    )

    # 读取对象的内容
    content = result.body.read()

    # 将内容保存到本地文件, 例如命名为test.txt
    with open('./test.txt', 'wb') as f:
        f.write(content)

    print(f'File saved to test.txt successfully!')

# 当此脚本被直接运行时,调用main函数
if __name__ == "__main__":
    main()  # 脚本入口,当文件被直接运行时调用main函数
package main

import (
	"context"
	"flag"
	"io"
	"log"
	"os"

	"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 // 对象名称
)

// init函数用于初始化命令行参数
func init() {
	flag.StringVar(&region, "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()

	// 检查bucket名称是否为空
	if len(bucketName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, bucket name required")
	}

	// 检查region是否为空
	if len(region) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, region required")
	}

	// 检查object名称是否为空
	if len(objectName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, object name required")
	}

	// 定义输出文件路径
	outputFile := "downloaded.file" // 替换为你希望保存的文件路径

	// 加载默认配置并设置凭证提供者和区域
	cfg := oss.LoadDefaultConfig().
		WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
		WithRegion(region)

	// 创建OSS客户端
	client := oss.NewClient(cfg)

	// 创建获取对象的请求
	request := &oss.GetObjectRequest{
		Bucket:    oss.Ptr(bucketName),      // 存储空间名称
		Key:       oss.Ptr(objectName),      // 对象名称
		VersionId: oss.Ptr("yourVersionId"), // 填写实际的版本ID
	}

	// 执行获取对象的操作并处理结果
	result, err := client.GetObject(context.TODO(), request)
	if err != nil {
		log.Fatalf("failed to get object %v", err)
	}
	defer result.Body.Close() // 确保在函数结束时关闭响应体

	// 一次性读取整个文件内容
	data, err := io.ReadAll(result.Body)
	if err != nil {
		log.Fatalf("failed to read object %v", err)
	}

	// 将内容写入到文件
	err = os.WriteFile(outputFile, data, 0644)
	if err != nil {
		log.Fatalf("failed to write to output file %v", err)
	}

	log.Printf("file downloaded successfully to %s", outputFile)
}
<?php

// 引入自动加载文件,确保依赖库能够正确加载
require_once __DIR__ . '/../vendor/autoload.php';

use AlibabaCloud\Oss\V2 as Oss;

// 定义命令行参数的描述信息
$optsdesc = [
    "region" => ['help' => 'The region in which the bucket is located.', 'required' => True], // Bucket所在的地域(必填)
    "endpoint" => ['help' => 'The domain names that other services can use to access OSS.', 'required' => False], // 访问域名(可选)
    "bucket" => ['help' => 'The name of the bucket', 'required' => True], // Bucket名称(必填)
    "key" => ['help' => 'The name of the object', 'required' => True], // 对象名称(必填)
];

// 将参数描述转换为getopt所需的长选项格式
// 每个参数后面加上":"表示该参数需要值
$longopts = \array_map(function ($key) {
    return "$key:";
}, array_keys($optsdesc));

// 解析命令行参数
$options = getopt("", $longopts);

// 验证必填参数是否存在
foreach ($optsdesc as $key => $value) {
    if ($value['required'] === True && empty($options[$key])) {
        $help = $value['help']; // 获取参数的帮助信息
        echo "Error: the following arguments are required: --$key, $help" . PHP_EOL;
        exit(1); // 如果必填参数缺失,则退出程序
    }
}

// 从解析的参数中提取值
$region = $options["region"]; // Bucket所在的地域
$bucket = $options["bucket"]; // Bucket名称
$key = $options["key"];       // 对象名称

// 加载环境变量中的凭证信息
// 使用EnvironmentVariableCredentialsProvider从环境变量中读取Access Key ID和Access Key Secret
$credentialsProvider = new Oss\Credentials\EnvironmentVariableCredentialsProvider();

// 使用SDK的默认配置
$cfg = Oss\Config::loadDefault();
$cfg->setCredentialsProvider($credentialsProvider); // 设置凭证提供者
$cfg->setRegion($region); // 设置Bucket所在的地域
if (isset($options["endpoint"])) {
    $cfg->setEndpoint($options["endpoint"]); // 如果提供了访问域名,则设置endpoint
}

// 创建OSS客户端实例
$client = new Oss\Client($cfg);

// 创建GetObjectRequest对象,用于获取指定对象的内容
$request = new Oss\Models\GetObjectRequest(
                bucket: $bucket,
                key: $key,
                versionId:"yourVersionId", //填写实际的版本号ID
);

// 执行获取对象操作
$result = $client->getObject($request);

// 定义要保存的本地文件路径
$localFilePath = './test/file.txt'; // 请替换为实际的文件路径

// 将内容写入本地文件
file_put_contents($localFilePath, $result->body->getContents());

// 打印获取结果
// 输出HTTP状态码、请求ID以及对象的内容
printf(
    'status code:' . $result->statusCode . PHP_EOL . // HTTP状态码,例如200表示成功
    'request id:' . $result->requestId . PHP_EOL  // 请求ID,用于调试或追踪请求
);

使用命令行工具ossutil

关于使用ossutil在已开启版本控制的Bucket中下载文件的具体操作,请参见cp(下载文件)

使用REST API

如果您的程序自定义要求较高,您可以直接发起REST API请求。直接发起REST API请求需要手动编写代码计算签名。更多信息,请参见GetObject

删除文件

开启版本控制后,您可以通过指定Object版本ID或者配置LifecycleObject永久删除。如果删除Object时未指定版本ID,则Bucket中将插入一个删除标记(Delete Marker)作为当前版本。

重要
  • 开启版本控制后,如果删除Object时未指定版本ID,默认不会删除Object的当前版本以及历史版本。

  • 同一Bucket禁止同时开通OSS-HDFS服务和版本控制,否则可能导致OSS-HDFS服务异常。为确保服务稳定性,请尽快暂停版本控制,并配置生命周期规则清理删除标记。

    具体操作,请参见同时开通OSS-HDFS服务和版本控制的Bucket如何处理?

您还可以通过生命周期规则的Expiration元素指定Object当前版本过期,或通过NoncurrentVersionExpiration元素永久删除非当前版本Object。详细说明如下

  • Expiration:应用于当前Object版本,通过添加删除标记将当前版本作为非当前版本保留。

  • NoncurrentVersionExpiration:适用于非当前版本Object,永久删除这些Object版本,且无法恢复。

关于版本控制结合生命周期的更多信息,请参见生命周期配置元素

以下分别说明在未指定版本ID以及指定版本ID的情况下,执行DELETE操作时Object的删除行为。

  • 如果未指定Object的版本ID,则OSS会插入一个删除标记作为当前版本,该删除标记也会有相应的唯一版本ID,但没有相关数据和ACL等,如下图所示(当前版本为删除标记,且版本ID=444444)。

  • 如果指定了Object的版本ID,则永久删除该指定版本的Object,如下图所示(即删除版本ID=333333Object)。

使用OSS控制台

为了减少存储费用,建议您及时删除不再需要的历史版本Object。

警告

历史版本Object被删除后无法恢复,请谨慎操作。

  1. 登录OSS管理控制台

  2. 单击Bucket 列表,然后单击目标Bucket名称。

  3. 在左侧导航栏,选择文件管理>文件列表

  4. 文件列表页面,单击历史版本右侧的显示

  5. 找到不再需要的历史版本Object,根据实际选择相应操作。

    • 如果要删除的历史版本Object为删除标记,请直接单击操作列的彻底删除

    • 如果要删除的历史版本Object不为删除标记,请将鼠标移动到文件操作列的image.png图标上单击彻底删除

    您也可以批量选中待删除的历史版本,单击页面下方的彻底删除

  6. 单击确定

    您也可以通过配置生命周期规则,定期自动删除历史版本Object。更多信息,请参见生命周期规则介绍

使用阿里云SDK

以下仅列举常见SDK在已开启版本控制的Bucket中删除指定版本文件的代码示例。关于其他SDK删除指定版本文件的代码示例,请参见SDK简介

import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.common.comm.SignVersion;

public class Demo {
    public static void main(String[] args) throws Exception {
        // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
        String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
        // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        // 填写Bucket名称,例如examplebucket。
        String bucketName = "examplebucket";
        // 填写Object的完整路径。Object完整路径中不能包含Bucket名称。
        String objectName = "exampledir/object";
        String versionId  = "CAEQMxiBgICAof2D0BYiIDJhMGE3N2M1YTI1NDQzOGY5NTkyNTI3MGYyMzJm****";
        // 填写Bucket所在地域。以华东1(杭州)为例,Region填写为cn-hangzhou。
        String region = "cn-hangzhou";

        // 创建OSSClient实例。
        // 当OSSClient实例不再使用时,调用shutdown方法以释放资源。
        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);        
        OSS ossClient = OSSClientBuilder.create()
        .endpoint(endpoint)
        .credentialsProvider(credentialsProvider)
        .clientConfiguration(clientBuilderConfiguration)
        .region(region)               
        .build();

        try {
            // 删除指定版本的Object。
            ossClient.deleteVersion(bucketName, objectName , versionId);
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }
}
const OSS = require("ali-oss");

const client = new OSS({
  // yourregion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
  region: 'yourregion',
  // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
  accessKeyId: process.env.OSS_ACCESS_KEY_ID,
  accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
  authorizationV4: true,
  // 填写存储空间名称。
  bucket: 'yourbucketname'
});

// 指定Object的versionId。
const versionId = "versionId";
// 指定Object。
const objectName = "exampleobject.txt";
async function deleteVersionObject() {
  const result = await client.delete(objectName, {
    versionId,
  });
  console.log(result);
}

deleteVersionObject();
using Aliyun.OSS;
using Aliyun.OSS.Common;

// yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
var endpoint = "yourEndpoint";
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
var accessKeyId = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_ID");
var accessKeySecret = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_SECRET");
// 填写Bucket名称,例如examplebucket。
var bucketName = "examplebucket";
// 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。
var objectName = "exampledir/exampleobject.txt";
// 填写Object的版本ID或删除标记的版本ID。
var versionid = "yourObjectVersionidOrDelMarkerVersionid";
// 填写Bucket所在地域对应的Region。以华东1(杭州)为例,Region填写为cn-hangzhou。
const string region = "cn-hangzhou";

// 创建ClientConfiguration实例,按照您的需要修改默认参数。
var conf = new ClientConfiguration();

// 设置v4签名。
conf.SignatureVersion = SignatureVersion.V4;

// 创建OssClient实例。
var client = new OssClient(endpoint, accessKeyId, accessKeySecret, conf);
client.SetRegion(region);
try
{
    // 指定Object的versionId,也可以是删除标记的versionId。
    var request = new DeleteObjectRequest(bucketName, objectName)
    {
        VersionId = versionid
    };
    client.DeleteObject(request);
    Console.WriteLine("Delete object succeeded");
}
catch (Exception ex)
{
    Console.WriteLine("Delete object failed. {0}", ex.Message);
}
#include <alibabacloud/oss/OssClient.h>
using namespace AlibabaCloud::OSS;

int main(void)
{
    /* 初始化OSS账号信息。*/
            
    /* yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。*/
    std::string Endpoint = "yourEndpoint";
    /* yourRegion填写Bucket所在地域对应的Region。以华东1(杭州)为例,Region填写为cn-hangzhou。*/
    std::string Region = "yourRegion";
    /* 填写Bucket名称,例如examplebucket。*/
    std::string BucketName = "examplebucket";
    /* 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。*/
    std::string ObjectName = "exampledir/exampleobject.txt";

    /* 初始化网络等资源。*/
    InitializeSdk();

    ClientConfiguration conf;
    conf.signatureVersion = SignatureVersionType::V4;
    /* 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。*/
    auto credentialsProvider = std::make_shared<EnvironmentVariableCredentialsProvider>();
    OssClient client(Endpoint, credentialsProvider, conf);
    client.SetRegion(Region);

    /* 删除指定versionId的Object或指定versionId的删除标记关联的Object。*/
    auto outcome = client.DeleteObject(DeleteObjectRequest(BucketName, ObjectName, "yourObjectVersionIdOrDeleteMarkerVersionId"));
    /* 如果指定的是Object的versionId,则返回的delete_marker为None且返回的versionId为指定Object的versionId。*/
    /* 如果指定的是删除标记的versionId,则返回的delete_marker为True且返回的versionId为指定删除标记的versionId。*/
    if (!outcome.isSuccess()) {
        /* 异常处理。*/
        std::cout << "DeleteObject fail" <<
        ",code:" << outcome.error().Code() <<
        ",message:" << outcome.error().Message() <<
        ",requestId:" << outcome.error().RequestId() << std::endl;
        return -1;
    }

    /* 释放网络等资源。*/
    ShutdownSdk();
    return 0;
}
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 // 存储空间名称
	objectName string // 对象名称
)

// init函数用于初始化命令行参数
func init() {
	flag.StringVar(&region, "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()

	// 检查bucket名称是否为空
	if len(bucketName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, bucket name required")
	}

	// 检查region是否为空
	if len(region) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, region required")
	}

	// 检查对象名称是否为空
	if len(objectName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, object name required")
	}

	// 加载默认配置并设置凭证提供者和区域
	cfg := oss.LoadDefaultConfig().
		WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
		WithRegion(region)

	// 创建OSS客户端
	client := oss.NewClient(cfg)

	// 创建删除对象的请求
	request := &oss.DeleteObjectRequest{
		Bucket:    oss.Ptr(bucketName),      // 存储空间名称
		Key:       oss.Ptr(objectName),      // 对象名称
		VersionId: oss.Ptr("yourVersionId"), // 填写实际的版本ID
	}

	// 执行删除对象的操作并处理结果
	result, err := client.DeleteObject(context.TODO(), request)
	if err != nil {
		log.Fatalf("failed to delete object %v", err)
	}

	// 打印删除对象的结果
	log.Printf("delete object result:%#v\n", result)
}
<?php

// 引入自动加载文件,确保依赖库能够正确加载
require_once __DIR__ . '/../vendor/autoload.php';

use AlibabaCloud\Oss\V2 as Oss;

// 定义命令行参数的描述信息
$optsdesc = [
    "region" => ['help' => 'The region in which the bucket is located.', 'required' => True], // Bucket所在的地域(必填)
    "endpoint" => ['help' => 'The domain names that other services can use to access OSS.', 'required' => False], // 访问域名(可选)
    "bucket" => ['help' => 'The name of the bucket', 'required' => True], // Bucket名称(必填)
    "key" => ['help' => 'The name of the object', 'required' => True], // 对象名称(必填)
];

// 将参数描述转换为getopt所需的长选项格式
// 每个参数后面加上":"表示该参数需要值
$longopts = \array_map(function ($key) {
    return "$key:";
}, array_keys($optsdesc));

// 解析命令行参数
$options = getopt("", $longopts);

// 验证必填参数是否存在
foreach ($optsdesc as $key => $value) {
    if ($value['required'] === True && empty($options[$key])) {
        $help = $value['help']; // 获取参数的帮助信息
        echo "Error: the following arguments are required: --$key, $help" . PHP_EOL;
        exit(1); // 如果必填参数缺失,则退出程序
    }
}

// 从解析的参数中提取值
$region = $options["region"]; // Bucket所在的地域
$bucket = $options["bucket"]; // Bucket名称
$key = $options["key"];       // 对象名称

// 加载环境变量中的凭证信息
// 使用EnvironmentVariableCredentialsProvider从环境变量中读取Access Key ID和Access Key Secret
$credentialsProvider = new Oss\Credentials\EnvironmentVariableCredentialsProvider();

// 使用SDK的默认配置
$cfg = Oss\Config::loadDefault();
$cfg->setCredentialsProvider($credentialsProvider); // 设置凭证提供者
$cfg->setRegion($region); // 设置Bucket所在的地域
if (isset($options["endpoint"])) {
    $cfg->setEndpoint($options["endpoint"]); // 如果提供了访问域名,则设置endpoint
}

// 创建OSS客户端实例
$client = new Oss\Client($cfg);

// 创建DeleteObjectRequest对象,用于删除指定的对象
$request = new Oss\Models\DeleteObjectRequest(
            bucket: $bucket,
            key: $key,
            versionId:"yourversionid", //指定要删除的对象版本号
);

// 执行删除对象操作
$result = $client->deleteObject($request);

// 打印删除结果
// 输出HTTP状态码和请求ID,用于验证删除是否成功
printf(
    'status code:' . $result->statusCode . PHP_EOL . // HTTP状态码,例如204表示删除成功
    'request id:' . $result->requestId . PHP_EOL     // 请求ID,用于调试或追踪请求
);

使用命令行工具ossutil

关于使用ossutil在已开启版本控制的Bucket中删除文件的具体操作, 请参见rm(删除)

使用REST API

如果您的程序自定义要求较高,您可以直接发起REST API请求。直接发起REST API请求需要手动编写代码计算签名。更多信息,请参见DeleteObject

恢复文件

开启版本控制后,BucketObject的所有版本都将得以保留。您可以通过恢复指定历史版本的方式,使得任意Object的历史版本成为当前版本。

您可以通过以下两种方式将Object的历史版本恢复至当前版本:

  • 通过CopyObject来恢复Object的历史版本

    复制的Object将成为该Object的当前版本,且所有Object版本都将保留。

    如下图所示,将原Object的历史版本(ID=222222)复制到同一个Bucket中,OSS将为该Object生成新的版本(ID=444444),并将其置为该Object的当前版本。因此,该Object同时具有历史版本(ID=222222)以及当前版本(ID=444444)。

  • 通过删除Object的当前版本来恢复Object的历史版本

    如下图所示,当您通过DELETE versionId的方式永久删除当前Object版本(ID=222222)后, 下一个历史版本(ID=111111)成为了该Object的当前版本。

重要

由于Object的当前版本删除后无法恢复,建议您通过CopyObject的方式来恢复Object的历史版本。

使用OSS控制台

  1. 登录OSS管理控制台

  2. 单击Bucket 列表,然后单击目标Bucket名称。

  3. 在左侧导航栏,选择文件管理>文件列表

  4. 文件列表页面,单击历史版本右侧的显示

  5. 将指定历史版本的Object恢复为当前版本。

    重要

    同一个Object仅允许恢复其中的某个历史版本,且该历史版本不能为删除标记。

    • 恢复单个Object

      单击目标历史版本操作列的恢复

    • 恢复多个Object

      选中目标历史版本,单击页面下方的恢复后,在弹出的对话框,单击确定

使用阿里云SDK

以下仅列举常见SDK在已开启版本控制的Bucket中拷贝指定版本文件的代码示例。关于其他SDK拷贝指定版本文件的代码示例,请参见SDK简介

import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.common.comm.SignVersion;
import com.aliyun.oss.model.*;

public class Demo {
    public static void main(String[] args) throws Exception {
        // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
        String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
        // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        // 填写源Bucket名称。
        String sourceBucketName = "srcexamplebucket";
        // 填写源Object的完整路径。Object完整路径中不能包含Bucket名称。
        String sourceObjectName = "srcexampleobject.txt";
        // 填写与源Bucket处于同一地域的目标Bucket名称。
        String destinationBucketName = "desexamplebucket";
        // 填写目标Object的完整路径。Object完整路径中不能包含Bucket名称。
        String destinationObjectName = "desexampleobject.txt";
        String versionId  = "CAEQMxiBgICAof2D0BYiIDJhMGE3N2M1YTI1NDQzOGY5NTkyNTI3MGYyMzJm****";
        // 填写Bucket所在地域。以华东1(杭州)为例,Region填写为cn-hangzhou。
        String region = "cn-hangzhou";

        // 创建OSSClient实例。
        // 当OSSClient实例不再使用时,调用shutdown方法以释放资源。
        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);        
        OSS ossClient = OSSClientBuilder.create()
        .endpoint(endpoint)
        .credentialsProvider(credentialsProvider)
        .clientConfiguration(clientBuilderConfiguration)
        .region(region)               
        .build();

        try {
            CopyObjectRequest copyObjectRequest = new CopyObjectRequest(sourceBucketName, sourceObjectName, destinationBucketName, destinationObjectName);
            copyObjectRequest.setSourceVersionId(versionId);
            CopyObjectResult copyObjectResult = ossClient.copyObject(copyObjectRequest);
            System.out.println("ETag: " + copyObjectResult.getETag() + " LastModified: " + copyObjectResult.getLastModified());
            System.out.println("dest object versionid: " + copyObjectResult.getVersionId());
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }
}
const OSS = require('ali-oss');

const client = new OSS({
  // yourregion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
  region: 'yourregion',
  // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
  accessKeyId: process.env.OSS_ACCESS_KEY_ID,
  accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
  authorizationV4: true,
  // yourbucketname填写存储空间名称。
  bucket: 'yourbucketname'
});

// 指定拷贝源Object的versionId。
const versionId = 'versionId';
// 指定拷贝源Object。
const srcObject = 'srcObject.txt';
// 指定拷贝源Bucket。
const srcBucket = 'srcBucket;
// 指定拷贝目标Object。
const targetObject = 'targetObject.txt';
async function Copy() {
  try {
    const result = await client.copy(targetObject, srcObject, srcBucket, {
      meta: {
        versionId: versionId
      }
    });

    console.log(result);
  } catch (error) {
    console.error(error);
  }
}

Copy()
using Aliyun.OSS;
using Aliyun.OSS.Common;
// yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
var endpoint = "yourEndpoint";
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
var accessKeyId = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_ID");
var accessKeySecret = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_SECRET");
// 填写源Bucket名称。
var sourceBucket = "yourSourceBucketName";
// 填写源Object的完整路径。Object完整路径中不能包含Bucket名称。
var sourceObject = "yourSourceObjectName";
// 填写与源Bucket处于同一地域的目标Bucket名称。
var targetBucket = "yourDestBucketName";
// 填写目标Object的完整路径。Object完整路径中不能包含Bucket名称。
var targetObject = "yourDestObjectName";
// 填写Object的版本ID。
var versionid = "yourArchiveObjectVersionid";
// 填写Bucket所在地域对应的Region。以华东1(杭州)为例,Region填写为cn-hangzhou。
const string region = "cn-hangzhou";

// 创建ClientConfiguration实例,按照您的需要修改默认参数。
var conf = new ClientConfiguration();

// 设置v4签名。
conf.SignatureVersion = SignatureVersion.V4;

// 创建OssClient实例。
var client = new OssClient(endpoint, accessKeyId, accessKeySecret, conf);
client.SetRegion(region);
try
{
    var metadata = new ObjectMetadata();
    metadata.AddHeader("mk1", "mv1");
    metadata.AddHeader("mk2", "mv2");
    var req = new CopyObjectRequest(sourceBucket, sourceObject, targetBucket, targetObject)
    {
        // 如果NewObjectMetadata为null,则为COPY模式(即拷贝源文件的元数据),非null则为REPLACE模式(即覆盖源文件的元数据)。
        NewObjectMetadata = metadata, 
        // 指定Object的版本ID。
        SourceVersionId = versionid
    };
    // 拷贝文件。
    var result = client.CopyObject(req);
    Console.WriteLine("Copy object succeeded, vesionid:{0}", result.VersionId);
}
catch (OssException ex)
{
    Console.WriteLine("Failed with error code: {0}; Error info: {1}. \nRequestID: {2} \tHostID: {3}",
        ex.ErrorCode, ex.Message, ex.RequestId, ex.HostId);
}
catch (Exception ex)
{
    Console.WriteLine("Failed with error info: {0}", ex.Message);
}
#include <alibabacloud/oss/OssClient.h>
using namespace AlibabaCloud::OSS;

int main(void)
{
    /* 初始化OSS账号信息。*/
            
    /* yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。*/
    std::string Endpoint = "yourEndpoint";
    /* yourRegion填写Bucket所在地域对应的Region。以华东1(杭州)为例,Region填写为cn-hangzhou。*/
    std::string Region = "yourRegion";
    /* 填写源Bucket名称,例如srcexamplebucket。*/
    std::string SourceBucketName = "srcexamplebucket";
    /* 填写与源Bucket处于同一地域的目标Bucket名称,例如destbucket。*/
    std::string CopyBucketName = "destbucket";
    /* 填写源Object的完整路径,完整路径中不能包含Bucket名称,例如srcdir/scrobject.txt。*/
    std::string SourceObjectName = "srcdir/scrobject.txt";
    /* 填写目标Object的完整路径,完整路径中不能包含Bucket名称,例如destdir/destobject.txt。*/
    std::string CopyObjectName = "destdir/destobject.txt";


    /* 初始化网络等资源。*/
    InitializeSdk();

    ClientConfiguration conf;
    conf.signatureVersion = SignatureVersionType::V4;
    /* 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。*/
    auto credentialsProvider = std::make_shared<EnvironmentVariableCredentialsProvider>();
    OssClient client(Endpoint, credentialsProvider, conf);
    client.SetRegion(Region);

    CopyObjectRequest request(CopyBucketName, CopyObjectName);
    request.setCopySource(SourceBucketName, SourceObjectName);
    /* 填写源Object的版本ID。*/
    request.setVersionId("yourSourceObjectVersionId");

    /* 拷贝指定版本的Object。*/
    auto outcome = client.CopyObject(request);

    if (outcome.isSuccess()) {
        std::cout << "versionid:" << outcome.result().VersionId() << std::endl;
    }
    else {
        /* 异常处理。*/
        std::cout << "CopyObject fail" <<
        ",code:" << outcome.error().Code() <<
        ",message:" << outcome.error().Message() <<
        ",requestId:" << outcome.error().RequestId() << std::endl;
        return -1;
    }

    /* 释放网络等资源。*/
    ShutdownSdk();
    return 0;
}
import time
import argparse
import alibabacloud_oss_v2 as oss

# 创建命令行参数解析器,并描述脚本用途:解冻对象示例
parser = argparse.ArgumentParser(description="restore object sample")

# 添加命令行参数 --region,表示存储空间所在的区域,必需参数
parser.add_argument('--region', help='The region in which the bucket is located.', required=True)
# 添加命令行参数 --bucket,表示存储空间的名称,必需参数
parser.add_argument('--bucket', help='The name of the bucket.', required=True)
# 添加命令行参数 --endpoint,表示其他服务可用来访问OSS的域名,非必需参数
parser.add_argument('--endpoint', help='The domain names that other services can use to access OSS')
# 添加命令行参数 --key,表示对象的名称,必需参数
parser.add_argument('--key', help='The name of the object.', required=True)
# 添加命令行参数 --version_id,表示对象的版本ID,必需参数
parser.add_argument('--version_id', help='The version ID of the object.', required=True)

def main():
    # 解析命令行提供的参数,获取用户输入的值
    args = parser.parse_args()

    # 从环境变量中加载访问OSS所需的认证信息,用于身份验证
    credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()

    # 使用SDK的默认配置创建配置对象,并设置认证提供者
    cfg = oss.config.load_default()
    cfg.credentials_provider = credentials_provider
    
    # 设置配置对象的区域属性,根据用户提供的命令行参数
    cfg.region = args.region

    # 如果提供了自定义endpoint,则更新配置对象中的endpoint属性
    if args.endpoint is not None:
        cfg.endpoint = args.endpoint

    # 使用上述配置初始化OSS客户端,准备与OSS交互
    client = oss.Client(cfg)

    # 发送请求以解冻对象
    result = client.restore_object(oss.RestoreObjectRequest(
        bucket=args.bucket,           # 指定存储空间名称
        key=args.key,                 # 指定对象名称
        version_id=args.version_id,   # 指定对象的版本ID
        restore_request=oss.RestoreRequest(
            days=1,                    # 指定解冻后对象的保留天数
            # 可选:设置冷归档、深度冷归档的解冻优先级,可设置为:Expedited、Standard、Bulk,默认值为Standard
            # tier="Expedited",
        )
    ))

    # 打印操作结果的状态码、请求ID、版本ID以及解冻优先级等信息,以便确认请求状态
    print(f'status code: {result.status_code},'
          f' request id: {result.request_id},'
          f' version id: {result.version_id},'
          f' restore priority: {result.restore_priority},'  # 解冻优先级(如果有)
          )

    # 循环检查对象是否已经完成解冻
    while True:
        # 获取对象头部信息
        result = client.head_object(oss.HeadObjectRequest(
            bucket=args.bucket,
            key=args.key,
            version_id=args.version_id,
        ))

        # 检查解冻状态
        if result.restore and result.restore != 'ongoing-request="true"':
            print('restore is success')  # 解冻成功
            break
        else:
            # 暂停5秒后再次检查
            time.sleep(5)
            print(result.restore)  # 打印当前解冻状态

# 当此脚本被直接执行时,调用main函数开始处理逻辑
if __name__ == "__main__":
    main()  # 脚本入口点,控制程序流程从这里开始
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 // 存储空间名称
	objectName string // 对象名称
)

// init函数用于初始化命令行参数
func init() {
	flag.StringVar(&region, "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()

	// 检查bucket名称是否为空
	if len(bucketName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, bucket name required")
	}

	// 检查region是否为空
	if len(region) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, region required")
	}

	// 检查object名称是否为空
	if len(objectName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, object name required")
	}

	// 加载默认配置并设置凭证提供者和区域
	cfg := oss.LoadDefaultConfig().
		WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
		WithRegion(region)

	// 创建OSS客户端
	client := oss.NewClient(cfg)

	// 创建解冻对象的请求
	request := &oss.RestoreObjectRequest{
		Bucket:    oss.Ptr(bucketName),      // 存储空间名称
		Key:       oss.Ptr(objectName),      // 对象名称
		VersionId: oss.Ptr("yourVersionId"), //填写实际的版本ID
		RestoreRequest: &oss.RestoreRequest{
			Days: 3, // 设置解冻状态的持续天数为3天
		},
	}

	// 发送解冻对象的请求
	result, err := client.RestoreObject(context.TODO(), request)
	if err != nil {
		log.Fatalf("failed to restore object %v", err)
	}

	// 打印解冻对象的结果
	log.Printf("restore object result:%#v\n", result)
}
<?php

// 引入自动加载文件,确保依赖库能够正确加载
require_once __DIR__ . '/../vendor/autoload.php';

use AlibabaCloud\Oss\V2 as Oss;

// 定义命令行参数的描述信息
$optsdesc = [
    "region" => ['help' => 'The region in which the bucket is located.', 'required' => True], // Bucket所在的地域(必填)
    "endpoint" => ['help' => 'The domain names that other services can use to access OSS.', 'required' => False], // 访问域名(可选)
    "bucket" => ['help' => 'The name of the bucket', 'required' => True], // Bucket名称(必填)
    "key" => ['help' => 'The name of the object', 'required' => True], // 对象名称(必填)
];

// 将参数描述转换为getopt所需的长选项格式
// 每个参数后面加上":"表示该参数需要值
$longopts = \array_map(function ($key) {
    return "$key:";
}, array_keys($optsdesc));

// 解析命令行参数
$options = getopt("", $longopts);

// 验证必填参数是否存在
foreach ($optsdesc as $key => $value) {
    if ($value['required'] === True && empty($options[$key])) {
        $help = $value['help']; // 获取参数的帮助信息
        echo "Error: the following arguments are required: --$key, $help" . PHP_EOL;
        exit(1); // 如果必填参数缺失,则退出程序
    }
}

// 从解析的参数中提取值
$region = $options["region"]; // Bucket所在的地域
$bucket = $options["bucket"]; // Bucket名称
$key = $options["key"];       // 对象名称

// 加载环境变量中的凭证信息
// 使用EnvironmentVariableCredentialsProvider从环境变量中读取Access Key ID和Access Key Secret
$credentialsProvider = new Oss\Credentials\EnvironmentVariableCredentialsProvider();

// 使用SDK的默认配置
$cfg = Oss\Config::loadDefault();
$cfg->setCredentialsProvider($credentialsProvider); // 设置凭证提供者
$cfg->setRegion($region); // 设置Bucket所在的地域
if (isset($options["endpoint"])) {
    $cfg->setEndpoint($options["endpoint"]); // 如果提供了访问域名,则设置endpoint
}

// 创建OSS客户端实例
$client = new Oss\Client($cfg);

// 创建RestoreObjectRequest对象,用于恢复归档存储类型对象
$request = new Oss\Models\RestoreObjectRequest(
                bucket: $bucket,
                key: $key,
                versionId:"yourVersionId", // 填写需要恢复的版本ID
            );

// 执行恢复对象操作
$result = $client->restoreObject($request);

// 打印恢复结果
printf(
    'status code:' . $result->statusCode . PHP_EOL . // HTTP状态码,例如200表示成功
    'request id:' . $result->requestId . PHP_EOL     // 请求ID,用于调试或追踪请求
);

使用命令行工具ossutil

关于使用ossutil在已开启版本控制的Bucket中将历史版本Object恢复为当前版本Object的具体操作,请参见revert(恢复版本)

使用REST API

如果您的程序自定义要求较高,您可以直接发起REST API请求。直接发起REST API请求需要手动编写代码计算签名。更多信息,请参见CopyObject