All Products
Search
Document Center

Object Storage Service:Manage file metadata (Go SDK V2)

Last Updated:Mar 20, 2026

Object metadata is a set of key-value pairs attached to an OSS object. OSS supports two categories of metadata: standard HTTP headers (such as Content-Type, Expires, and Cache-Control) and custom metadata (arbitrary key-value pairs with keys prefixed with x-oss-meta-). This document shows how to set metadata during upload, retrieve it, and update it on existing objects.

Prerequisites

Before you begin, ensure that you have:

  • An OSS bucket in a known region

  • oss:PutObject permission to set object metadata

  • oss:GetObject permission to retrieve object metadata

  • Access credentials configured as environment variables (see Configure access credentials)

Usage notes

  • The sample code uses the China (Hangzhou) region (cn-hangzhou) and a public endpoint by default. To access OSS from other Alibaba Cloud services in the same region, use an internal endpoint instead. For region-to-endpoint mappings, see Regions and endpoints.

  • For RAM (Resource Access Management) permission details, see Grant custom permissions to a RAM user.

Supported metadata fields

The following fields can be set on an object when uploading or copying. Standard HTTP headers are returned in the response when the object is downloaded or queried via HeadObject.

FieldTypeDescription
Expiresstring (RFC 1123)Expiration time of the object. Pass a string formatted with time.Time.Format(time.RFC1123).
Acloss.ObjectACLTypeAccess control list (ACL) for the object, for example, oss.ObjectACLPublicRead.
Metadatamap[string]stringCustom key-value pairs. Keys must be prefixed with x-oss-meta-.

Set metadata during upload

Pass metadata fields in PutObjectRequest. The same pattern applies to other upload operations.

package main

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

	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss"
	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials"
)

var (
	region     string
	bucketName string
	objectName string
)

func init() {
	flag.StringVar(&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()

	if len(bucketName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, bucket name required")
	}

	if len(region) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, region required")
	}

	if len(objectName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, object name required")
	}

	content := "hi oss"

	cfg := oss.LoadDefaultConfig().
		WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
		WithRegion(region)

	client := oss.NewClient(cfg)

	request := &oss.PutObjectRequest{
		Bucket:  oss.Ptr(bucketName),
		Key:     oss.Ptr(objectName),
		Body:    strings.NewReader(content),
		Expires: oss.Ptr(time.Date(2038, 12, 31, 12, 0, 0, 0, time.UTC).Format(time.RFC1123)), // RFC 1123 string required
		Acl:     oss.ObjectACLPublicRead,
		Metadata: map[string]string{
			"Author": "alibaba oss sdk",
			"Date":   "2024-07-01",
		},
	}

	result, err := client.PutObject(context.TODO(), request)
	if err != nil {
		log.Fatalf("failed to put object %v", err)
	}

	log.Printf("put object result:%#v\n", result)
}

Retrieve object metadata

OSS provides two methods to retrieve object metadata. Choose based on how much information you need:

MethodReturnsUse when
HeadObjectAll metadata, including custom metadata and standard HTTP headersYou need custom metadata or the full set of headers
GetObjectMetaPartial metadata only: ContentLength, ETag, LastModified, LastAccessTime, VersionId, and HashCRC64You need a lightweight check without retrieving the full header set

Retrieve all metadata with HeadObject

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
)

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()

	if len(bucketName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, bucket name required")
	}

	if len(region) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, region required")
	}

	if len(objectName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, object name required")
	}

	cfg := oss.LoadDefaultConfig().
		WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
		WithRegion(region)

	client := oss.NewClient(cfg)

	request := &oss.HeadObjectRequest{
		Bucket: oss.Ptr(bucketName),
		Key:    oss.Ptr(objectName),
	}

	result, err := client.HeadObject(context.TODO(), request)
	if err != nil {
		log.Fatalf("failed to head object %v", err)
	}

	log.Printf("head object result:%#v\n", result)
}

Retrieve partial metadata with GetObjectMeta

GetObjectMeta returns only: ContentLength, ETag, LastModified, LastAccessTime, VersionId, and HashCRC64. Use it when you do not need custom metadata and want to minimize response overhead.

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
)

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()

	if len(bucketName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, bucket name required")
	}

	if len(region) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, region required")
	}

	if len(objectName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, object name required")
	}

	cfg := oss.LoadDefaultConfig().
		WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
		WithRegion(region)

	client := oss.NewClient(cfg)

	request := &oss.GetObjectMetaRequest{
		Bucket: oss.Ptr(bucketName),
		Key:    oss.Ptr(objectName),
	}

	result, err := client.GetObjectMeta(context.TODO(), request)
	if err != nil {
		log.Fatalf("failed to get object meta %v", err)
	}

	log.Printf("get object meta result:%#v\n", result)
}

Update metadata on an existing object

OSS does not provide a dedicated metadata update operation. To update metadata on an existing object, copy the object and set MetadataDirective to "Replace". This replaces all existing metadata with the values you specify in the copy request; the original metadata is discarded.

Two copy methods are available:

MethodBest for
CopyObjectStandard copy operation
Copier.Copy (copy manager)Large objects; handles multipart copy automatically

Update metadata with CopyObject

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
	srcBucketName  string
	srcObjectName  string
	destBucketName string
	destObjectName string
)

func init() {
	flag.StringVar(&region, "region", "", "The region in which the bucket is located.")
	flag.StringVar(&srcBucketName, "src-bucket", "", "The name of the source bucket.")
	flag.StringVar(&srcObjectName, "src-object", "", "The name of the source object.")
	flag.StringVar(&destBucketName, "dest-bucket", "", "The name of the destination bucket.")
	flag.StringVar(&destObjectName, "dest-object", "", "The name of the destination object.")
}

func main() {
	flag.Parse()

	if len(srcBucketName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, source bucket name required")
	}

	if len(region) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, region required")
	}

	if len(destBucketName) == 0 {
		destBucketName = srcBucketName // Default to the source bucket
	}

	if len(srcObjectName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, source object name required")
	}

	if len(destObjectName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, destination object name required")
	}

	cfg := oss.LoadDefaultConfig().
		WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
		WithRegion(region)

	client := oss.NewClient(cfg)

	// New metadata to apply; the original metadata is replaced entirely
	metaData := map[string]string{
		"x-oss-meta-tag1": "value1",
		"x-oss-meta-tag2": "value2",
	}

	copyRequest := &oss.CopyObjectRequest{
		Bucket:            oss.Ptr(destBucketName),
		Key:               oss.Ptr(destObjectName),
		SourceKey:         oss.Ptr(srcObjectName),
		SourceBucket:      oss.Ptr(srcBucketName),
		Metadata:          metaData,
		MetadataDirective: oss.Ptr("Replace"), // Replace, not copy, the source metadata
	}

	copyResult, err := client.CopyObject(context.TODO(), copyRequest)
	if err != nil {
		log.Fatalf("failed to copy object: %v", err)
	}

	log.Printf("copy object result versionId:%#v\n", copyResult)
}

Update metadata with Copier.Copy (copy manager)

Use Copier.Copy for large objects. The copy manager handles multipart copy automatically. You can replace the original metadata, clear the original metadata, or update parts of the original metadata. After the copy operation is complete, you can choose whether to delete the source object.

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
	srcBucketName  string
	srcObjectName  string
	destBucketName string
	destObjectName string
)

func init() {
	flag.StringVar(&region, "region", "", "The region in which the bucket is located.")
	flag.StringVar(&srcBucketName, "src-bucket", "", "The name of the source bucket.")
	flag.StringVar(&srcObjectName, "src-object", "", "The name of the source object.")
	flag.StringVar(&destBucketName, "dest-bucket", "", "The name of the destination bucket.")
	flag.StringVar(&destObjectName, "dest-object", "", "The name of the destination object.")
}

func main() {
	flag.Parse()

	if len(srcBucketName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, bucket name required")
	}

	if len(region) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, region required")
	}

	if len(destBucketName) == 0 {
		destBucketName = srcBucketName // Default to the source bucket
	}

	if len(srcObjectName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, src object name required")
	}

	if len(destObjectName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, destination object name required")
	}

	cfg := oss.LoadDefaultConfig().
		WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
		WithRegion(region)

	client := oss.NewClient(cfg)

	// Create a copy manager for large objects
	c := client.NewCopier()

	// New metadata to apply; the original metadata is replaced entirely
	metaData := map[string]string{
		"x-oss-meta-tag1": "value1",
		"x-oss-meta-tag2": "value2",
	}

	copyRequest := &oss.CopyObjectRequest{
		Bucket:            oss.Ptr(destBucketName),
		Key:               oss.Ptr(destObjectName),
		SourceKey:         oss.Ptr(srcObjectName),
		SourceBucket:      oss.Ptr(srcBucketName),
		Metadata:          metaData,
		MetadataDirective: oss.Ptr("Replace"), // Replace, not copy, the source metadata
	}

	result, err := c.Copy(context.TODO(), copyRequest)
	if err != nil {
		log.Fatalf("failed to copy object %v", err)
	}

	// Optionally delete the source object after the copy completes
	deleteRequest := &oss.DeleteObjectRequest{
		Bucket: oss.Ptr(srcBucketName),
		Key:    oss.Ptr(srcObjectName),
	}

	deleteResult, err := client.DeleteObject(context.TODO(), deleteRequest)
	if err != nil {
		log.Fatalf("failed to delete object %v", err)
	}

	log.Printf("copy object result:%#v\n", result)
	log.Printf("delete object result:%#v\n", deleteResult)
}

References