This topic describes how to copy objects in a versioned bucket. You can use CopyObject to copy an object that is up to 1 GB in size and use UploadPartCopy to copy an object larger than 1 GB.
Copy a small object
You can use CopyObject to copy an object that is up to 1 GB in size from a source bucket to a destination bucket within the same region.
- By default, the x-oss-copy-source header in a CopyObject request specifies the current version of the object to copy. If the current version of the object to copy is a delete marker, 404 Not Found is returned to indicate that the object does not exist. You can add a version ID in the x-oss-copy-source header to copy a specified object version. Delete markers cannot be copied.
- You can copy a previous version of an object to the same bucket. The copied previous version becomes the current version of the object. This way, you can restore an object to a specified previous version.
- If versioning is enabled for the destination bucket, OSS generates a unique version ID for the destination object. The version ID is returned in the response as the x-oss-version-id header value. If versioning is disabled or suspended for the destination bucket, OSS generates a version whose version ID is null for the destination object and overwrites the original version whose version ID is null.
- Append objects in a bucket with versioning enabled or suspended cannot be copied.
package main
import (
"fmt"
"os"
"github.com/aliyun/aliyun-oss-go-sdk/oss"
)
func main() {
// Create an OSSClient instance.
client, err := oss.New("<yourEndpoint>", "<yourAccessKeyId>", "<yourAccessKeySecret>")
if err ! = nil {
fmt.Println("Error:", err)
os.Exit(-1)
}
bucketName := "<yourBucketName>"
objectName := "<yourObjectName>"
destObjectName := "<yourDestObjectName>"
// Specify the name of the bucket.
bucket, err := client.Bucket(bucketName)
if err ! = nil {
fmt.Println("Error:", err)
os.Exit(-1)
}
// Copy the specified version of the object to another object in the same bucket and query the version ID of the destination object.
var retHeader http.Header
_, err = bucket.CopyObject(objectName, destObjectName, oss.VersionId("yourObjectVersionId"), oss.GetResponseHeader(&retHeader))
if err ! = nil {
fmt.Println("Error:", err)
os.Exit(-1)
}
// Display the version ID of the destination object.
fmt.Println("x-oss-version-id:", oss.GetVersionId(retHeader))
fmt.Println("x-oss-copy-source-version-id:", oss.GetCopySrcVersionId(retHeader))
}
For more information about how to copy small objects, see CopyObject.
Copy a large object
To copy an object larger than 1 GB, you must split the object into parts and copy them sequentially by using UploadPartCopy.
If versionId is not specified in the request and the current version of the source object is a delete marker, OSS returns 404 Not Found. If versionId is specified in the request and the specified version of the source object is a delete marker, OSS returns 400 Bad Request.
package main
import (
"fmt"
"net/http"
"os"
"time"
"github.com/aliyun/aliyun-oss-go-sdk/oss"
)
func main() {
// Create an OSSClient instance.
client, err := oss.New("<yourEndpoint>", "<yourAccessKeyId>", "<yourAccessKeySecret>")
if err ! = nil {
fmt.Println("Error:", err)
os.Exit(-1)
}
// Specify the name of the bucket.
bucket, err := client.Bucket("yourBucketName")
if err ! = nil {
fmt.Println("Error:", err)
os.Exit(-1)
}
bucketName := "yourBucketName"
objectName := "yourObjectName"
fileName := "yourFileName"
futureDate := time.Date(2049, time.January, 10, 23, 0, 0, 0, time.UTC)
var retHeader http.Header
chunks, err := oss.SplitFileByPartNum(fileName, 3)
// Upload a large object as the source object.
err = bucket.PutObjectFromFile(objectName, fileName, oss.GetResponseHeader(&retHeader))
if err ! = nil {
fmt.Println("Error:", err)
os.Exit(-1)
}
// Query the version ID of the uploaded source object.
versionId := oss.GetVersionId(retHeader)
options := []oss.Option{
oss.Expires(futureDate), oss.Meta("my", "myprop"),
}
// Specify the name of the destination object.
objectDest := objectName + "dest"
var parts []oss.UploadPart
// Set parameters for object copy.
copyOptions := []oss.Option{
oss.VersionId(versionId), oss.GetResponseHeader(&retHeader),
}
// Copy the large object.
imu, err := bucket.InitiateMultipartUpload(objectDest, options...)
for _, chunk := range chunks {
part, err := bucket.UploadPartCopy(imu, bucketName, objectName, chunk.Offset, chunk.Size, (int)(chunk.Number), copyOptions...)
if err ! = nil {
fmt.Println("Error:", err)
os.Exit(-1)
}
parts = append(parts, part)
// Display the value of the x-oss-copy-source-version-id header.
fmt.Println("x-oss-copy-source-version-id:", oss.GetCopySrcVersionId(retHeader))
}
_, err = bucket.CompleteMultipartUpload(imu, parts, oss.GetResponseHeader(&retHeader))
if err ! = nil {
fmt.Println("Error:", err)
os.Exit(-1)
}
// Display the value of x-oss-version-id.
fmt.Println("x-oss-version-id:", oss.GetVersionId(retHeader))
}
For more information about multipart copy, see UploadPartCopy.