فهرست منبع

add object tagging related apis

hangzws 6 سال پیش
والد
کامیت
6cbae959a1
7فایلهای تغییر یافته به همراه337 افزوده شده و 20 حذف شده
  1. 192 0
      oss/bucket_test.go
  2. 15 3
      oss/option.go
  3. 1 0
      oss/type.go
  4. 2 1
      sample.go
  5. 33 14
      sample/bucket_lifecycle.go
  6. 19 2
      sample/copy_object.go
  7. 75 0
      sample/object_tagging.go

+ 192 - 0
oss/bucket_test.go

@@ -2778,3 +2778,195 @@ func (s *OssBucketSuite) TestUploadObjectWithWebpFormat(c *C) {
 	bucket.DeleteObject(objectName)
 	client.DeleteBucket(bucketName)
 }
+
+func (s *OssBucketSuite) TestPutObjectTagging(c *C) {
+	// put object with tagging
+	objectName := objectNamePrefix + randStr(8)
+	tag1 := Tag{
+		Key:   randStr(8),
+		Value: randStr(16),
+	}
+	tag2 := Tag{
+		Key:   randStr(8),
+		Value: randStr(16),
+	}
+	tagging := ObjectTagging{
+		Tags: []Tag{tag1, tag2},
+	}
+	err := s.bucket.PutObject(objectName, strings.NewReader(randStr(1024)), Tagging(tagging))
+	c.Assert(err, IsNil)
+
+	headers, err := s.bucket.GetObjectDetailedMeta(objectName)
+	taggingCount, err := strconv.Atoi(headers["x-oss-tagging-count"][0])
+	c.Assert(err, IsNil)
+	c.Assert(taggingCount, Equals, 2)
+
+	// put tagging
+	tag := Tag{
+		Key:   randStr(8),
+		Value: randStr(16),
+	}
+	tagging.Tags = []Tag{tag}
+	err = s.bucket.PutObjectTagging(objectName, tagging)
+	c.Assert(err, IsNil)
+
+	tagging, err = s.bucket.GetObjectTagging(objectName)
+	c.Assert(len(tagging.Tags), Equals, 1)
+	c.Assert(tagging.Tags[0].Key, Equals, tag.Key)
+	c.Assert(tagging.Tags[0].Value, Equals, tag.Value)
+
+	//put tagging, the length of the key exceeds 128
+	tag = Tag{
+		Key:   randStr(129),
+		Value: randStr(16),
+	}
+	tagging.Tags = []Tag{tag}
+	err = s.bucket.PutObjectTagging(objectName, tagging)
+	c.Assert(err, NotNil)
+
+	//put tagging, the length of the value exceeds 256
+	tag = Tag{
+		Key:   randStr(8),
+		Value: randStr(257),
+	}
+	tagging.Tags = []Tag{tag}
+	err = s.bucket.PutObjectTagging(objectName, tagging)
+	c.Assert(err, NotNil)
+
+	//put tagging, the lens of tags exceed 10
+	tagging.Tags = []Tag{}
+	for i := 0; i < 11; i++ {
+		tag = Tag{
+			Key:   randStr(8),
+			Value: randStr(16),
+		}
+		tagging.Tags = append(tagging.Tags, tag)
+	}
+	err = s.bucket.PutObjectTagging(objectName, tagging)
+	c.Assert(err, NotNil)
+
+	//put tagging, invalid value of tag key
+	tag = Tag{
+		Key:   randStr(8) + "&",
+		Value: randStr(16),
+	}
+	tagging.Tags = []Tag{tag}
+	err = s.bucket.PutObjectTagging(objectName, tagging)
+	c.Assert(err, NotNil)
+
+	//put tagging, invalid value of tag value
+	tag = Tag{
+		Key:   randStr(8),
+		Value: randStr(16) + "&",
+	}
+	tagging.Tags = []Tag{tag}
+	err = s.bucket.PutObjectTagging(objectName, tagging)
+	c.Assert(err, NotNil)
+
+	//put tagging, repeated tag keys
+	tag1 = Tag{
+		Key:   randStr(8),
+		Value: randStr(16),
+	}
+	tag2 = Tag{
+		Key:   tag1.Key,
+		Value: randStr(16),
+	}
+	tagging.Tags = []Tag{tag1, tag2}
+	err = s.bucket.PutObjectTagging(objectName, tagging)
+	c.Assert(err, NotNil)
+
+	s.bucket.DeleteObject(objectName)
+}
+
+func (s *OssBucketSuite) TestGetObjectTagging(c *C) {
+	// get object which has 2 tags
+	objectName := objectNamePrefix + randStr(8)
+	tag1 := Tag{
+		Key:   randStr(8),
+		Value: randStr(16),
+	}
+	tag2 := Tag{
+		Key:   randStr(8),
+		Value: randStr(16),
+	}
+	tagging := ObjectTagging{
+		Tags: []Tag{tag1, tag2},
+	}
+	err := s.bucket.PutObject(objectName, strings.NewReader(randStr(1024)), Tagging(tagging))
+	c.Assert(err, IsNil)
+
+	tagging, err = s.bucket.GetObjectTagging(objectName)
+	c.Assert(len(tagging.Tags), Equals, 2)
+	c.Assert(tagging.Tags[0].Key, Equals, tag1.Key)
+	c.Assert(tagging.Tags[0].Value, Equals, tag1.Value)
+	c.Assert(tagging.Tags[1].Key, Equals, tag2.Key)
+	c.Assert(tagging.Tags[1].Value, Equals, tag2.Value)
+
+	// get tagging of an object that is not exist
+	err = s.bucket.DeleteObject(objectName)
+	c.Assert(err, IsNil)
+	tagging, err = s.bucket.GetObjectTagging(objectName)
+	c.Assert(err, NotNil)
+	c.Assert(len(tagging.Tags), Equals, 0)
+
+	// get object which has no tag
+	objectName = objectNamePrefix + randStr(8)
+	err = s.bucket.PutObject(objectName, strings.NewReader(randStr(1024)))
+	c.Assert(err, IsNil)
+	tagging, err = s.bucket.GetObjectTagging(objectName)
+	c.Assert(err, IsNil)
+	c.Assert(len(tagging.Tags), Equals, 0)
+
+	// copy object, with tagging option
+	destObjectName := objectName + "-dest"
+	tagging.Tags = []Tag{tag1, tag2}
+	_, err = s.bucket.CopyObject(objectName, destObjectName, Tagging(tagging))
+	c.Assert(err, IsNil)
+	tagging, err = s.bucket.GetObjectTagging(objectName)
+	c.Assert(err, IsNil)
+	c.Assert(len(tagging.Tags), Equals, 0)
+
+	// copy object, with tagging option, the value of tagging directive is "REPLACE"
+	_, err = s.bucket.CopyObject(objectName, destObjectName, Tagging(tagging), TaggingDirective(TaggingReplace))
+	c.Assert(err, IsNil)
+	tagging, err = s.bucket.GetObjectTagging(objectName)
+	c.Assert(err, IsNil)
+	c.Assert(len(tagging.Tags), Equals, 2)
+	c.Assert(tagging.Tags[0].Key, Equals, tag1.Key)
+	c.Assert(tagging.Tags[0].Value, Equals, tag1.Value)
+	c.Assert(tagging.Tags[1].Key, Equals, tag2.Key)
+	c.Assert(tagging.Tags[1].Value, Equals, tag2.Value)
+
+	s.bucket.DeleteObject(objectName)
+	s.bucket.DeleteObject(destObjectName)
+}
+
+func (s *OssBucketSuite) TestDeleteObjectTagging(c *C) {
+	// delete object tagging, the object is not exist
+	objectName := objectNamePrefix + randStr(8)
+	err := s.bucket.DeleteObjectTagging(objectName)
+	c.Assert(err, NotNil)
+
+	// delete object tagging
+	tag := Tag{
+		Key:   randStr(8),
+		Value: randStr(16),
+	}
+	tagging := ObjectTagging{
+		Tags: []Tag{tag},
+	}
+	err = s.bucket.PutObject(objectName, strings.NewReader(randStr(1024)), Tagging(tagging))
+	c.Assert(err, IsNil)
+	err = s.bucket.DeleteObjectTagging(objectName)
+	c.Assert(err, IsNil)
+	tagging, err = s.bucket.GetObjectTagging(objectName)
+	c.Assert(err, IsNil)
+	c.Assert(len(tagging.Tags), Equals, 0)
+
+	//delete object tagging again
+	err = s.bucket.DeleteObjectTagging(objectName)
+	c.Assert(err, IsNil)
+
+	s.bucket.DeleteObject(objectName)
+}

+ 15 - 3
oss/option.go

@@ -3,6 +3,7 @@ package oss
 import (
 	"fmt"
 	"net/http"
+	"net/url"
 	"strconv"
 	"strings"
 	"time"
@@ -202,9 +203,20 @@ func RequestPayer(payerType PayerType) Option {
 	return setHeader(HTTPHeaderOssRequester, string(payerType))
 }
 
-// Tagging is an option to set object tagging, notice: the value is url.QueryEscape(TagA)=url.QueryEscape(A) & url.QueryEscape(TagB)=url.QueryEscape(B)...
-func Tagging(value string) Option {
-	return setHeader(HTTPHeaderOssTagging, value)
+// Tagging is an option to set object tagging
+func Tagging(tagging ObjectTagging) Option {
+	if len(tagging.Tags) == 0 {
+		return nil
+	}
+
+	taggingValue := ""
+	for index, tag := range tagging.Tags {
+		if index != 0 {
+			taggingValue += "&"
+		}
+		taggingValue += url.QueryEscape(tag.Key) + "=" + url.QueryEscape(tag.Value)
+	}
+	return setHeader(HTTPHeaderOssTagging, taggingValue)
 }
 
 // TaggingDirective is an option to set X-Oss-Metadata-Directive header

+ 1 - 0
oss/type.go

@@ -47,6 +47,7 @@ type LifecycleRule struct {
 	ID                   string                         `xml:"ID,omitempty"`                   // The rule ID
 	Prefix               string                         `xml:"Prefix"`                         // The object key prefix
 	Status               string                         `xml:"Status"`                         // The rule status (enabled or not)
+	Tags                 []Tag                          `xml:"Tag,omitempty"`                  // the tags property
 	Expiration           *LifecycleExpiration           `xml:"Expiration,omitempty"`           // The expiration property
 	Transitions          []LifecycleTransition          `xml:"Transition,omitempty"`           // The transition property
 	AbortMultipartUpload *LifecycleAbortMultipartUpload `xml:"AbortMultipartUpload,omitempty"` // The AbortMultipartUpload property

+ 2 - 1
sample.go

@@ -4,7 +4,7 @@ package main
 
 import (
 	"fmt"
-    
+
 	"github.com/aliyun/aliyun-oss-go-sdk/sample"
 )
 
@@ -31,6 +31,7 @@ func main() {
 	sample.SignURLSample()
 
 	sample.ArchiveSample()
+	sample.ObjectTaggingSample()
 
 	fmt.Println("All samples completed")
 }

+ 33 - 14
sample/bucket_lifecycle.go

@@ -20,7 +20,7 @@ func BucketLifecycleSample() {
 		HandleError(err)
 	}
 
-	// Case 1: Set the lifecycle. The rule ID is rule1 and the applied objects' prefix is one and expired time is 11/11/2015
+	// Case 1: Set the lifecycle. The rule ID is rule1 and the applied objects' prefix is one and the last modified Date is before 2015/11/11
 	expriation := oss.LifecycleExpiration{
 		CreatedBeforeDate: "2015-11-11T00:00:00.000Z",
 	}
@@ -36,14 +36,14 @@ func BucketLifecycleSample() {
 		HandleError(err)
 	}
 
-	// Get the bucket's lifecycle
+	// Case 2: Get the bucket's lifecycle
 	lc, err := client.GetBucketLifecycle(bucketName)
 	if err != nil {
 		HandleError(err)
 	}
 	fmt.Printf("Bucket Lifecycle:%v, %v\n", lc.Rules, *lc.Rules[0].Expiration)
 
-	// Case 2: Set the lifecycle, The rule ID is id2 and the applied objects' prefix is two and the expired time is three days after the object created.
+	// Case 3: Set the lifecycle, The rule ID is rule2 and the applied objects' prefix is two. The object start with the prefix will be transited to IA storage Type 3 days latter, and to archive storage type 30 days latter
 	transitionIA := oss.LifecycleTransition{
 		Days:         3,
 		StorageClass: oss.StorageIA,
@@ -64,13 +64,7 @@ func BucketLifecycleSample() {
 		HandleError(err)
 	}
 
-	// Get the bucket's lifecycle
-	lc, err = client.GetBucketLifecycle(bucketName)
-	if err != nil {
-		HandleError(err)
-	}
-	fmt.Printf("Bucket Lifecycle:%v\n", lc.Rules)
-
+	// Case 4: Set the lifecycle, The rule ID is rule3 and the applied objects' prefix is three. The object start with the prefix will be transited to IA storage Type 3 days latter, and to archive storage type 30 days latter, the uncompleted multipart upload will be abort 3 days latter.
 	abortMPU := oss.LifecycleAbortMultipartUpload{
 		Days: 3,
 	}
@@ -86,14 +80,39 @@ func BucketLifecycleSample() {
 		HandleError(err)
 	}
 
-	// Get the bucket's lifecycle
-	lc, err = client.GetBucketLifecycle(bucketName)
+	// Case 5: Set the lifecycle. The rule ID is rule4 and the applied objects' has the tagging which prefix is four and the last modified Date is before 2015/11/11
+	expriation = oss.LifecycleExpiration{
+		CreatedBeforeDate: "2015-11-11T00:00:00.000Z",
+	}
+	tag1 := oss.Tag{
+		Key:   "key1",
+		Value: "value1",
+	}
+	tag2 := oss.Tag{
+		Key:   "key2",
+		Value: "value2",
+	}
+	rule4 := oss.LifecycleRule{
+		ID:         "rule4",
+		Prefix:     "four",
+		Status:     "Enabled",
+		Tags:       []oss.Tag{tag1, tag2},
+		Expiration: &expriation,
+	}
+	rules = []oss.LifecycleRule{rule4}
+	err = client.SetBucketLifecycle(bucketName, rules)
 	if err != nil {
 		HandleError(err)
 	}
-	fmt.Printf("Bucket Lifecycle:%v, %v\n", lc.Rules, *lc.Rules[1].AbortMultipartUpload)
 
-	// Delete bucket's Lifecycle
+	// for Debug only
+	//lc, err = client.GetBucketLifecycle(bucketName)
+	//if err != nil {
+	//	HandleError(err)
+	//}
+	//fmt.Printf("Bucket Lifecycle:%v, %v\n", lc.Rules, *lc.Rules[0].Expiration)
+
+	// Case 6: Delete bucket's Lifecycle
 	err = client.DeleteBucketLifecycle(bucketName)
 	if err != nil {
 		HandleError(err)

+ 19 - 2
sample/copy_object.go

@@ -106,8 +106,25 @@ func CopyObjectSample() {
 
 	// Case 7: Set the storage classes.OSS provides three storage classes: Standard, Infrequent Access, and Archive.
 	// Copy a object in the same bucket, and set object's storage-class to Archive.
-	_, rr := bucket.CopyObject(objectKey, objectKey+"DestArchive", oss.ObjectStorageClass("Archive"))
-	if rr != nil {
+	_, err = bucket.CopyObject(objectKey, objectKey+"DestArchive", oss.ObjectStorageClass("Archive"))
+	if err != nil {
+		HandleError(err)
+	}
+
+	// Case 8: Copy object with tagging, the value of tagging directive is REPLACE
+	tag1 := oss.Tag{
+		Key:   "key1",
+		Value: "value1",
+	}
+	tag2 := oss.Tag{
+		Key:   "key2",
+		Value: "value2",
+	}
+	tagging := oss.ObjectTagging{
+		Tags: []oss.Tag{tag1, tag2},
+	}
+	_, err = bucket.CopyObject(objectKey, objectKey+"WithTagging", oss.Tagging(tagging), oss.TaggingDirective(oss.TaggingReplace))
+	if err != nil {
 		HandleError(err)
 	}
 

+ 75 - 0
sample/object_tagging.go

@@ -0,0 +1,75 @@
+package sample
+
+import (
+	"fmt"
+	"strings"
+
+	"github.com/aliyun/aliyun-oss-go-sdk/oss"
+)
+
+// ObjectTaggingSample shows how to set and get object Tagging
+func ObjectTaggingSample() {
+	// Create bucket
+	bucket, err := GetTestBucket(bucketName)
+	if err != nil {
+		HandleError(err)
+	}
+
+	// Create object
+	err = bucket.PutObject(objectKey, strings.NewReader("ObjectTaggingSample"))
+	if err != nil {
+		HandleError(err)
+	}
+
+	// Case 1: Set Tagging of object
+	tag1 := oss.Tag{
+		Key:   "key1",
+		Value: "value1",
+	}
+	tag2 := oss.Tag{
+		Key:   "key2",
+		Value: "value2",
+	}
+	tagging := oss.ObjectTagging{
+		Tags: []oss.Tag{tag1, tag2},
+	}
+	err = bucket.PutObjectTagging(objectKey, tagging)
+	if err != nil {
+		HandleError(err)
+	}
+
+	// Case 2: Get Tagging of object
+	tagging, err = bucket.GetObjectTagging(objectKey)
+	if err != nil {
+		HandleError(err)
+	}
+	fmt.Printf("Object Tagging: %v\n", tagging)
+
+	tag3 := oss.Tag{
+		Key:   "key3",
+		Value: "value3",
+	}
+
+	// Case 3: Put object with tagging
+	tagging = oss.ObjectTagging{
+		Tags: []oss.Tag{tag1, tag2, tag3},
+	}
+	err = bucket.PutObject(objectKey, strings.NewReader("ObjectTaggingSample"), oss.Tagging(tagging))
+	if err != nil {
+		HandleError(err)
+	}
+
+	// Case 4: Delete Tagging of object
+	err = bucket.DeleteObjectTagging(objectKey)
+	if err != nil {
+		HandleError(err)
+	}
+
+	// Delete object and bucket
+	err = DeleteTestBucketAndObject(bucketName)
+	if err != nil {
+		HandleError(err)
+	}
+
+	fmt.Println("ObjectACLSample completed")
+}