版本控制应用于桶中所有对象。通过开启桶的版本控制,您可以在错误删除或者覆盖对象后,将对象回恢复至任意的历史版本。
目前支持多版本的接口包含 GetObject、GetObjectACL、CopyObject、UploadPartCopy、DeleteObject 等。调用相关接口时,您可通过可选参数 VersionID 指定操作对象的具体版本。
TOS 中桶的版本状态包含未开启、开启版本控制和暂停版本控制三种,本文介绍桶的多版本管理。
注意
tos:PutBucketVersioning
权限。tos:GetBucketVersioning
权限。package main import ( "context" "fmt" "github.com/volcengine/ve-tos-golang-sdk/v2/tos" "github.com/volcengine/ve-tos-golang-sdk/v2/tos/enum" "os" ) func checkErr(err error) { if err != nil { if serverErr, ok := err.(*tos.TosServerError); ok { fmt.Println("Error:", serverErr.Error()) fmt.Println("Request ID:", serverErr.RequestID) fmt.Println("Response Status Code:", serverErr.StatusCode) fmt.Println("Response Header:", serverErr.Header) fmt.Println("Response Err Code:", serverErr.Code) fmt.Println("Response Err Msg:", serverErr.Message) } else if clientErr, ok := err.(*tos.TosClientError); ok { fmt.Println("Error:", clientErr.Error()) fmt.Println("Client Cause Err:", clientErr.Cause.Error()) } else { fmt.Println("Error:", err) } panic(err) } } func main() { var ( accessKey = os.Getenv("TOS_ACCESS_KEY") secretKey = os.Getenv("TOS_SECRET_KEY") // Bucket 对应的 Endpoint,以华北2(北京)为例:https://tos-cn-beijing.volces.com endpoint = "https://tos-cn-beijing.volces.com" region = "cn-beijing" // 填写 BucketName bucketName = "*** Provide your bucket name ***" ctx = context.Background() ) // 初始化客户端 client, err := tos.NewClientV2(endpoint, tos.WithRegion(region), tos.WithCredentials(tos.NewStaticCredentials(accessKey, secretKey))) checkErr(err) // 开启多版本 output, err := client.PutBucketVersioning(ctx, &tos.PutBucketVersioningInput{ Bucket: bucketName, Status: enum.VersioningStatusEnable, }) fmt.Println("PutBucketVersioning Request ID:", output.RequestID) // 关闭多版本 output, err = client.PutBucketVersioning(ctx, &tos.PutBucketVersioningInput{ Bucket: bucketName, Status: enum.VersioningStatusSuspended, }) fmt.Println("PutBucketVersioning Request ID:", output.RequestID) }
package main import ( "context" "fmt" "io/ioutil" "github.com/volcengine/ve-tos-golang-sdk/v2/tos" ) func checkErr(err error) { if err != nil { if serverErr, ok := err.(*tos.TosServerError); ok { fmt.Println("Error:", serverErr.Error()) fmt.Println("Request ID:", serverErr.RequestID) fmt.Println("Response Status Code:", serverErr.StatusCode) fmt.Println("Response Header:", serverErr.Header) fmt.Println("Response Err Code:", serverErr.Code) fmt.Println("Response Err Msg:", serverErr.Message) } else if clientErr, ok := err.(*tos.TosClientError); ok { fmt.Println("Error:", clientErr.Error()) fmt.Println("Client Cause Err:", clientErr.Cause.Error()) } else { fmt.Println("Error:", err) } panic(err) } } func main() { var ( accessKey = os.Getenv("TOS_ACCESS_KEY") secretKey = os.Getenv("TOS_SECRET_KEY") // Bucket 对应的 Endpoint,以华北2(北京)为例:https://tos-cn-beijing.volces.com endpoint = "https://tos-cn-beijing.volces.com" region = "cn-beijing" // 填写 BucketName bucketName = "*** Provide your bucket name ***" objectKey = "example_dir/example.txt" ctx = context.Background() ) // 初始化客户端 client, err := tos.NewClientV2(endpoint, tos.WithRegion(region), tos.WithCredentials(tos.NewStaticCredentials(accessKey, secretKey))) checkErr(err) // 下载数据到内存 // 指定下载对象版本信息 versionID := "your object version id" getOutput, err := client.GetObjectV2(ctx, &tos.GetObjectV2Input{ Bucket: bucketName, Key: objectKey, VersionID: versionID, }) checkErr(err) fmt.Println("GetObjectV2 Request ID:", getOutput.RequestID) // 下载数据大小 fmt.Println("GetObjectV2 Response ContentLength", getOutput.ContentLength) defer getOutput.Content.Close() body, err := ioutil.ReadAll(getOutput.Content) checkErr(err) // 完成下载 fmt.Println("Get Object Content:", body) }
package main import ( "context" "fmt" "github.com/volcengine/ve-tos-golang-sdk/v2/tos" ) func checkErr(err error) { if err != nil { if serverErr, ok := err.(*tos.TosServerError); ok { fmt.Println("Error:", serverErr.Error()) fmt.Println("Request ID:", serverErr.RequestID) fmt.Println("Response Status Code:", serverErr.StatusCode) fmt.Println("Response Header:", serverErr.Header) fmt.Println("Response Err Code:", serverErr.Code) fmt.Println("Response Err Msg:", serverErr.Message) } else if clientErr, ok := err.(*tos.TosClientError); ok { fmt.Println("Error:", clientErr.Error()) fmt.Println("Client Cause Err:", clientErr.Cause.Error()) } else { fmt.Println("Error:", err) } panic(err) } } func main() { var ( accessKey = os.Getenv("TOS_ACCESS_KEY") secretKey = os.Getenv("TOS_SECRET_KEY") // Bucket 对应的 Endpoint,以华北2(北京)为例:https://tos-cn-beijing.volces.com endpoint = "https://tos-cn-beijing.volces.com" region = "cn-beijing" // 填写 BucketName bucketName = "*** Provide your bucket name ***" // 指定的 objectKey objectKey = "example_dir/example.txt" ctx = context.Background() versionID = "*** Provide object Version ID" ) // 初始化客户端 client, err := tos.NewClientV2(endpoint, tos.WithRegion(region), tos.WithCredentials(tos.NewStaticCredentials(accessKey, secretKey))) checkErr(err) // 删除存储桶中指定对象指定版本 output, err := client.DeleteObjectV2(ctx, &tos.DeleteObjectV2Input{ Bucket: bucketName, Key: objectKey, VersionID: versionID, }) checkErr(err) fmt.Println("DeleteObjectV2 Request ID:", output.RequestID) }
以下代码用于清空整个开启多版本桶的示例代码,包括删除所有对象的多个版本、删除删除标记的多个版本、删除所有未合并的对象。
package main import ( "context" "fmt" "os" "github.com/volcengine/ve-tos-golang-sdk/v2/tos" ) func checkErr(err error) { if err != nil { if serverErr, ok := err.(*tos.TosServerError); ok { fmt.Println("Error:", serverErr.Error()) fmt.Println("Request ID:", serverErr.RequestID) fmt.Println("Response Status Code:", serverErr.StatusCode) fmt.Println("Response Header:", serverErr.Header) fmt.Println("Response Err Code:", serverErr.Code) fmt.Println("Response Err Msg:", serverErr.Message) } else if clientErr, ok := err.(*tos.TosClientError); ok { fmt.Println("Error:", clientErr.Error()) fmt.Println("Client Cause Err:", clientErr.Cause.Error()) } else { fmt.Println("Error:", err) } panic(err) } } func main() { var ( accessKey = os.Getenv("TOS_ACCESS_KEY") secretKey = os.Getenv("TOS_SECRET_KEY") // Bucket 对应的 Endpoint,以华北2(北京)为例:https://tos-cn-beijing.volces.com endpoint = "https://tos-cn-beijing.volces.com" region = "cn-beijing" // 填写 BucketName bucketName = "*** Provide your bucket name ***" ctx = context.Background() ) // 初始化客户端 client, err := tos.NewClientV2(endpoint, tos.WithRegion(region), tos.WithCredentials(tos.NewStaticCredentials(accessKey, secretKey))) checkErr(err) // 删除桶中所有对象 truncated := true marker := "" versionIdMarker := "" for truncated { listOutput, err := client.ListObjectVersionsV2(ctx, &tos.ListObjectVersionsV2Input{ Bucket: bucketName, ListObjectVersionsInput: tos.ListObjectVersionsInput{ MaxKeys: 1000, KeyMarker: marker, VersionIDMarker: versionIdMarker, }, }) checkErr(err) for _, obj := range listOutput.Versions { // 删除多版本对象 output, err := client.DeleteObjectV2(ctx, &tos.DeleteObjectV2Input{ Bucket: bucketName, Key: obj.Key, VersionID: obj.VersionID, }) checkErr(err) fmt.Printf("Delete %s, Request ID: %s\n", obj.Key, output.RequestID) } // 删除标记信息 for _, deleteMarker := range listOutput.DeleteMarkers { output, err := client.DeleteObjectV2(ctx, &tos.DeleteObjectV2Input{ Bucket: bucketName, Key: deleteMarker.Key, VersionID: deleteMarker.VersionID, }) checkErr(err) fmt.Printf("Delete deleteMarker %s, Request ID: %s\n", deleteMarker.Key, output.RequestID) } truncated = listOutput.IsTruncated marker = listOutput.NextKeyMarker versionIdMarker = listOutput.NextVersionIDMarker } truncated = true marker = "" uploadIDMarker := "" for truncated { output, err := client.ListMultipartUploadsV2(ctx, &tos.ListMultipartUploadsV2Input{ Bucket: bucketName, MaxUploads: 1000, KeyMarker: marker, UploadIDMarker: uploadIDMarker, }) checkErr(err) for _, upload := range output.Uploads { abortUpload, err := client.AbortMultipartUpload(ctx, &tos.AbortMultipartUploadInput{ Bucket: bucketName, Key: upload.Key, UploadID: upload.UploadID, }) checkErr(err) fmt.Println("AbortMultipartUpload Upload ID:", upload.UploadID, " Request ID:", abortUpload.RequestID) } truncated = output.IsTruncated marker = output.NextKeyMarker uploadIDMarker = output.NextUploadIDMarker } }