All Products
Search
Document Center

Object Storage Service:Perform multipart upload by using OSS SDK for Go

Last Updated:Dec 01, 2024

Object Storage Service (OSS) provides the multipart upload feature. Multipart upload allows you to split a large object into multiple parts to upload. After these parts are uploaded, you can call the CompleteMultipartUpload operation to combine the parts into a complete object.

Usage notes

  • In this topic, the public endpoint of the China (Hangzhou) region is used. If you want to access OSS from other Alibaba Cloud services in the same region as OSS, use an internal endpoint. For more information about OSS regions and endpoints, see Regions and endpoints.

  • In this topic, access credentials are obtained from environment variables. For more information about how to configure access credentials, see Configure access credentials.

  • In this topic, an OSSClient instance is created by using an OSS endpoint. If you want to create an OSSClient instance by using custom domain names or Security Token Service (STS), see Initialization.

  • To perform multipart upload, you must have the oss:PutObject permission. For more information, see Attach a custom policy to a RAM user.

  • OSS SDK for Go 2.2.5 and later support all attributes that are included in the following sample code.

Process

To upload a local file by using multipart upload, perform the following steps:

  1. Initiate a multipart upload task.

    Call the Bucket.InitiateMultipartUpload method to obtain a unique upload ID in OSS.

  2. Upload parts.

    Call the Bucket.UploadPart method to upload the parts.

    Note
    • For parts that are uploaded by running a multipart upload task with a specific upload ID, the part numbers identify their relative positions in an object. If you upload a part and reuse its part number to upload another part, the new part overwrites the original part.

    • OSS includes the MD5 hash of each uploaded part in the ETag header in the response.

    • OSS calculates the MD5 hash of uploaded parts and compares the MD5 hash with the MD5 hash that is calculated by OSS SDK for Go. If the two hashes are different, OSS returns the InvalidDigest error code.

  3. Complete the multipart upload task.

    After you upload all parts, call the Bucket.CompleteMultipartUpload method to combine the parts into a complete object.

Examples

The following sample code provides an example on how to run a multipart upload task by following the multipart upload process:

package main

import (
	"fmt"
	"log"
	"os"

	"github.com/aliyun/aliyun-oss-go-sdk/oss"
)

func main() {
	// Obtain access credentials from environment variables. Before you run the sample code, make sure that the OSS_ACCESS_KEY_ID and OSS_ACCESS_KEY_SECRET environment variables are configured. 
	provider, err := oss.NewEnvironmentVariableCredentialsProvider()
	if err != nil {
		log.Fatalf("Error: %v", err)
	}

	// Create an OSSClient instance. 
	// Specify the endpoint of the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the endpoint to https://oss-cn-hangzhou.aliyuncs.com. Specify your actual endpoint. 
	// Specify the region in which the bucket is located. For example, if the bucket is located in the China (Hangzhou) region, set the region to cn-hangzhou.
	clientOptions := []oss.ClientOption{oss.SetCredentialsProvider(&provider)}
	clientOptions = append(clientOptions, oss.Region("yourRegion"))
	// Specify the version of the signature algorithm.
	clientOptions = append(clientOptions, oss.AuthVersion(oss.AuthV4))
	client, err := oss.New("yourEndpoint", "", "", clientOptions...)
	if err != nil {
		log.Fatalf("Error: %v", err)
	}

	// Specify the name of the bucket.
	bucketName := "examplebucket"
	// Specify the full path of the object. Do not include the bucket name in the full path. 
	objectName := "exampleobject.txt"
	// Specify the full path of the local file. By default, if you do not specify the path of the local file, the file is uploaded from the path of the project to which the sample program belongs. 
	localFilename := "/localpath/exampleobject.txt"

	bucket, err := client.Bucket(bucketName)
	if err != nil {
		log.Fatalf("Error: %v", err)
	}

        // Specify the part size. Unit: bytes. In this example, the part size is set to 5 MB. 
	partSize := int64(5 * 1024 * 1024)

	// Call the multipart upload function. 
	if err := uploadMultipart(bucket, objectName, localFilename, partSize); err != nil {
		log.Fatalf("Failed to upload multipart: %v", err)
	}

}

// Specify the multipart upload function.
func uploadMultipart(bucket *oss.Bucket, objectName, localFilename string, partSize int64) error {
	// Split the local file.
	chunks, err := oss.SplitFileByPartSize(localFilename, partSize)
	if err != nil {
		return fmt.Errorf("failed to split file into chunks: %w", err)
	}

	// Open the local file. 
	file, err := os.Open(localFilename)
	if err != nil {
		return fmt.Errorf("failed to open file: %w", err)
	}
	defer file.Close()

	// Step 1: Initiate a multipart upload task. 
	imur, err := bucket.InitiateMultipartUpload(objectName)
	if err != nil {
		return fmt.Errorf("failed to initiate multipart upload: %w", err)
	}

	// Step 2: Upload the parts. 
	var parts []oss.UploadPart
	for _, chunk := range chunks {
		part, err := bucket.UploadPart(imur, file, chunk.Size, chunk.Number)
		if err != nil {
			// If a part fails to be uploaded, cancel the multipart upload task. 
			if abortErr := bucket.AbortMultipartUpload(imur); abortErr != nil {
				log.Printf("Failed to abort multipart upload: %v", abortErr)
			}
			return fmt.Errorf("failed to upload part: %w", err)
		}
		parts = append(parts, part)
	}

	// Set the access control list (ACL) of the object to private. By default, the object inherits the ACL of the bucket. 
	objectAcl := oss.ObjectACL(oss.ACLPrivate)

	// Step 3: Complete the multipart upload task. 
	_, err = bucket.CompleteMultipartUpload(imur, parts, objectAcl)
	if err != nil {
		// If you fail to complete the multipart upload task, cancel the multipart upload task. 
		if abortErr := bucket.AbortMultipartUpload(imur); abortErr != nil {
			log.Printf("Failed to abort multipart upload: %v", abortErr)
		}
		return fmt.Errorf("failed to complete multipart upload: %w", err)
	}

	log.Printf("Multipart upload completed successfully.")
	return nil
}

FAQ

How do I cancel a multipart upload task?

In one of the following scenarios, you can use the Bucket.AbortMultipartUpload method to cancel a multipart upload task:

  1. Errors in an object

    • If you detect errors in the object during the upload process, such as object damage or malicious code, you can cancel the multipart upload task to prevent potential risks.

  2. Unstable network connection

    • If the network connection is unstable or interrupted, parts may be lost or damaged during the upload process. You can cancel the multipart upload task and initiate another multipart upload task to ensure data integrity and consistency.

  3. Resource limits

    • If your storage capacity is insufficient and the object that you want to upload is too large, you can cancel the multipart upload task, release storage resources, and allocate the resources to more important tasks.

  4. Accidental operations

    • If you accidentally initiate an unnecessary multipart upload task or upload an incorrect version of an object, you can cancel the multipart upload task.

...
if err = bucket.AbortMultipartUpload(imur); err != nil {
log.Fatalf("failed to abort multipart upload: %w", err)
}

log.Printf("Multipart upload aborted successfully.")

How do I list uploaded parts?

In one of the following scenarios, you can use the Bucket.ListUploadedParts method to list the uploaded parts in a multipart upload task:

Monitor the object upload progress

  1. Large object upload

    • When you upload a very large object, list the uploaded parts to ensure that the upload task runs as expected and problems are detected at the earliest opportunity.

  2. Resumable upload

    • When the network connection is unstable or interrupted during the object upload, you can view the uploaded parts to determine whether you need to re-upload the failed parts by using resumable upload.

  3. Troubleshooting

    • If an error occurs during the object upload, you can quickly identify the error by checking the uploaded parts, such as the upload failure of a specific part, and then resolve the error accordingly.

  4. Resource management

    • In scenarios that require strict control of resource usage, you can better manage the storage capacity and bandwidth resources to ensure that the resources are effectively used by monitoring the object upload progress.

...	
if lsRes, err := bucket.ListUploadedParts(imur); err != nil {
log.Fatalf("Failed to list uploaded parts: %v", err)
}

for _, upload := range lsRes.UploadedParts {
log.Printf("List PartNumber: %d, ETag: %s, LastModified: %v\n", upload.PartNumber, upload.ETag, upload.LastModified)
}

How do I list the multipart upload tasks of a bucket?

In one of the following scenarios, you can use the Bucket.ListMultipartUploads method to list all ongoing multipart upload tasks of a bucket:

Monitoring scenarios

  1. Batch object upload management

    • If you want to upload a large number of objects, you can use the ListMultipartUploads method to monitor all multipart upload tasks in real time to ensure that all objects are uploaded correctly.

  2. Fault detection and recovery

    • If you encounter network issues or other failures during the upload process, specific parts may fail to be uploaded. By monitoring ongoing multipart upload tasks, you can detect these issues at the earliest opportunity and take measures to resume the upload.

  3. Resource optimization and management

    • During large-scale object upload, you can monitor ongoing multipart upload tasks to optimize resource allocation, such as adjusting the bandwidth usage or optimizing upload policies based on the upload progress.

  4. Data migration

    • When you perform large-scale data migration, you can monitor all ongoing multipart upload tasks to ensure the smooth migration of data and detect and resolve potential issues at the earliest opportunity.

Parameter configuration

Parameter

Description

Delimiter

The character that is used to group objects by name. The objects whose names contain the same string from the prefix to the next occurrence of the delimiter are grouped as a single result element in the CommonPrefixes parameter.

MaxUploads

The maximum number of multipart upload tasks to return this time. Default value: 1000. Maximum value: 1000.

KeyMarker

Specifies that all multipart upload tasks with objects whose names are alphabetically after the value of the KeyMarker parameter are included in the list. You can use this parameter with the UploadIDMarker parameter to specify the starting position from which you want to list the returned results.

Prefix

The prefix that the returned object names must contain. If you use a prefix for a query, the returned object name contains the prefix.

UploadIDMarker

The starting position from which you want to list the returned results. This parameter is used together with the KeyMarker parameter.

  • If the KeyMarker parameter is not configured, this parameter is ignored.

  • If the KeyMarker parameter is configured, the response includes the following items:

    • Multipart upload tasks in which the object names are alphabetically after the value of the KeyMarker parameter.

    • Multipart upload tasks in which the object names are the same as the value of the KeyMarker parameter but whose upload IDs are greater than the value of the UploadIDMarker parameter.

  • List multipart upload tasks by using the default values of the parameters

    ...
    lsRes, err := bucket.ListMultipartUploads(oss.KeyMarker(keyMarker), oss.UploadIDMarker(uploadIdMarker))
    if err != nil {
    log.Fatalf("failed to list multipart uploads: %w", err)
    }
    
    for _, upload := range lsRes.Uploads {
    log.Printf("Upload: %s, UploadID: %s\n", upload.Key, upload.UploadID)
    }
  • Set the Prefix parameter to file and list multipart upload tasks

    ...
    lsRes, err := bucket.ListMultipartUploads(oss.Prefix('file'))
    if err != nil {
    log.Fatalf("failed to list multipart uploads with prefix: %w", err)
    }
    
    log.Printf("Uploads:", lsRes.Uploads)
  • Specify that up to 100 multipart upload tasks are returned

    ...
    lsRes, err := bucket.ListMultipartUploads(oss.MaxUploads(100))
    if err != nil {
    log.Fatalf("failed to list multipart uploads with limit: %w", err)
    }
    
    log.Printf("Uploads:", lsRes.Uploads)
  • Set the Prefix parameter to file and specify that up to 100 multipart upload tasks are returned

    ...
    lsRes, err := bucket.ListMultipartUploads(oss.Prefix("file"), oss.MaxUploads(100))
    if err != nil {
    log.Fatalf("failed to list multipart uploads with prefix and limit: %w", err)
    }
    
    log.Printf("Uploads:", lsRes.Uploads)

References

  • For the complete sample code that is used to perform multipart upload, visit GitHub.

  • A multipart upload involves three API operations. For more information about the operations, see the following topics:

  • For more information about the API operation that you can call to cancel a multipart upload task, see AbortMultipartUpload.

  • For more information about the API operation that you can call to list uploaded parts, see ListUploadedParts.

  • For more information about the API operation that you can call to list all ongoing multipart upload tasks, see ListMultipartUploads. Ongoing multipart upload tasks include tasks that were initiated but are not completed or canceled.