全部產品
Search
文件中心

Object Storage Service:分區上傳

更新時間:Nov 29, 2025

大檔案上傳面臨網路中斷風險和傳輸時間過長的挑戰。分區上傳通過將檔案分割為多個小分區並發傳輸,提供斷點續傳能力和傳輸效能最佳化,有效應對網路不穩定環境下的檔案傳輸需求。

工作原理

分區上傳將大檔案分割為多個小分區進行獨立處理,各分區獨立傳輸和校正,單個分區失敗時僅需重傳該分區,避免重新上傳整個檔案。分區上傳使用Upload ID作為任務標識符,確保所有分區正確歸屬於同一個上傳任務。核心流程分為三個步驟:

  1. 初始化上傳任務:調用InitiateMultipartUpload介面建立分區上傳任務,擷取唯一的Upload ID作為後續操作的標識符。

  2. 上傳檔案分區資料:將檔案切分為多個分區(Part)並發上傳,每個分區大小在100KB到5GB之間,支援斷點續傳。

  3. 合并分區完成上傳:調用CompleteMultipartUpload介面將所有分區按序號合并為完整的對象檔案。

實現大檔案分區上傳

重要

根據策略調整,為提升OSS服務的合規性和安全性,自2025年3月20日起,新開通OSS服務的使用者在中國內地地區的Bucket將無法通過預設外網網域名稱調用資料操作類API(如上傳、下載檔案),需通過自訂網域名(CNAME)方式訪問OSS服務。使用HTTPS協議訪問(如控制台)時,還需為自訂網域名配置SSL認證

根據應用情境和技術要求,可選擇圖形化工具、命令列工具或SDK來實現分區上傳功能。

說明
  • OSS控制台暫不支援分區上傳操作。

  • 支援上傳加密的壓縮檔,但不支援上傳目錄。

通過工具自動分區

對於日常開發、測試、營運或手動上傳情境,推薦使用圖形化或命令列工具,工具會自動處理分區邏輯,操作便捷。

通過SDK編程實現分區

各語言SDK提供完整的分區上傳介面封裝,支援自訂分區大小、並發控制和錯誤處理。以下為常見語言的SDK分區上傳樣本,更多語言的使用樣本請參見SDK參考中對應語言的範例程式碼。

運行代碼前需安裝對應語言的SDK並配置訪問憑證環境變數,使用RAM使用者或RAM角色時還需參考API和許可權說明進行介面授權。

Java SDK V2

import com.aliyun.sdk.service.oss2.OSSClient;
import com.aliyun.sdk.service.oss2.credentials.CredentialsProvider;
import com.aliyun.sdk.service.oss2.credentials.StaticCredentialsProvider;
import com.aliyun.sdk.service.oss2.io.BoundedInputStream;
import com.aliyun.sdk.service.oss2.models.*;
import com.aliyun.sdk.service.oss2.transport.BinaryData;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * OSS分區上傳樣本
 * 實現大檔案的分區上傳功能
 */
public class MultipartUpload {

    public static void main(String[] args) {
        // 從環境變數擷取訪問憑證
        String accessKeyId = System.getenv("OSS_ACCESS_KEY_ID");
        String accessKeySecret = System.getenv("OSS_ACCESS_KEY_SECRET");

        // 設定OSS地區和Endpoint
        String region = "cn-hangzhou";
        String endpoint = "oss-cn-hangzhou.aliyuncs.com";

        // 配置Bucket和檔案資訊
        String bucket = "example-bucket";
        String key = "dest.jpg";
        String filePath = "dest.jpg";

        // 建立憑證提供者
        CredentialsProvider provider = new StaticCredentialsProvider(accessKeyId, accessKeySecret);

        // 初始化OSS用戶端
        OSSClient client = OSSClient.newBuilder()
                .credentialsProvider(provider)
                .region(region)
                .endpoint(endpoint)
                .build();

        try {
            // 步驟1:初始化分區上傳
            InitiateMultipartUploadResult initiateResult = client.initiateMultipartUpload(
                    InitiateMultipartUploadRequest.newBuilder()
                            .bucket(bucket)
                            .key(key)
                            .build());

            String uploadId = initiateResult.initiateMultipartUpload().uploadId();
            System.out.printf("初始化分區上傳成功,狀態代碼:%d, 請求ID:%s, 上傳ID:%s\n",
                    initiateResult.statusCode(), initiateResult.requestId(), uploadId);

            // 步驟2:上傳分區
            File file = new File(filePath);
            long fileSize = file.length();
            long partSize = 100 * 1024; // 每個分區100KB
            int partNumber = 1;
            List<Part> uploadParts = new ArrayList<>();

            for (long start = 0; start < fileSize; start += partSize) {
                long curPartSize = Math.min(partSize, fileSize - start);

                // 讀取檔案分區並上傳
                try (InputStream is = new FileInputStream(file)) {
                    is.skip(start);
                    BoundedInputStream boundedInputStream = new BoundedInputStream(is, curPartSize);

                    // 上傳分區
                    UploadPartResult partResult = client.uploadPart(UploadPartRequest.newBuilder()
                            .bucket(bucket)
                            .key(key)
                            .uploadId(uploadId)
                            .partNumber((long) partNumber)
                            .body(BinaryData.fromStream(boundedInputStream))
                            .build());

                    System.out.printf("狀態代碼: %d, 請求ID: %s, 分區號: %d, ETag: %s\n",
                            partResult.statusCode(), partResult.requestId(), partNumber, partResult.eTag());

                    uploadParts.add(Part.newBuilder()
                            .partNumber((long) partNumber)
                            .eTag(partResult.eTag())
                            .build());
                }
                partNumber++;
            }

            // 步驟3:完成分區上傳
            uploadParts.sort((p1, p2) -> p1.partNumber().compareTo(p2.partNumber()));

            CompleteMultipartUpload completeMultipartUpload = CompleteMultipartUpload.newBuilder()
                    .parts(uploadParts)
                    .build();

            CompleteMultipartUploadResult completeResult = client.completeMultipartUpload(
                    CompleteMultipartUploadRequest.newBuilder()
                            .bucket(bucket)
                            .key(key)
                            .uploadId(uploadId)
                            .completeMultipartUpload(completeMultipartUpload)
                            .build());

            System.out.printf("完成分區上傳,狀態代碼:%d, 請求ID:%s, Bucket:%s, Key:%s, 位置:%s, ETag:%s\n",
                    completeResult.statusCode(), completeResult.requestId(), 
                    completeResult.completeMultipartUpload().bucket(),
                    completeResult.completeMultipartUpload().key(), 
                    completeResult.completeMultipartUpload().location(),
                    completeResult.completeMultipartUpload().eTag());

        } catch (Exception e) {
            System.out.printf("錯誤:\n%s", e);
            e.printStackTrace();
        } finally {
            // 關閉用戶端串連
            try {
                client.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

Java SDK V1

import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.common.comm.SignVersion;
import com.aliyun.oss.model.*;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

/**
 * OSS分區上傳樣本(V1 SDK)
 * 實現大檔案的分區上傳功能
 */
public class MultipartUpload {

    public static void main(String[] args) {
        // 從環境變數擷取訪問憑證
        String accessKeyId = System.getenv("OSS_ACCESS_KEY_ID");
        String accessKeySecret = System.getenv("OSS_ACCESS_KEY_SECRET");

        // 設定OSS地區和Endpoint
        String region = "cn-hangzhou";
        String endpoint = "oss-cn-hangzhou.aliyuncs.com";

        // 配置Bucket和檔案資訊
        String bucketName = "example-bucket";
        String objectName = "dest.jpg";
        String filePath = "dest.jpg";

        // 建立憑證提供者
        DefaultCredentialProvider provider = new DefaultCredentialProvider(accessKeyId, accessKeySecret);

        // 配置用戶端參數
        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);

        // 初始化OSS用戶端
        OSS ossClient = OSSClientBuilder.create()
                .credentialsProvider(provider)
                .clientConfiguration(clientBuilderConfiguration)
                .region(region)
                .endpoint(endpoint)
                .build();

        try {
            // 步驟1:初始化分區上傳
            InitiateMultipartUploadRequest initiateRequest = new InitiateMultipartUploadRequest(bucketName, objectName);
            InitiateMultipartUploadResult initiateResult = ossClient.initiateMultipartUpload(initiateRequest);
            String uploadId = initiateResult.getUploadId();
            System.out.printf("初始化分區上傳成功,上傳ID: %s\n", uploadId);

            // 步驟2:上傳分區
            File file = new File(filePath);
            long fileLength = file.length();
            long partSize = 100 * 1024L; // 每個分區100KB

            // 計算分區數量
            int partCount = (int) (fileLength / partSize);
            if (fileLength % partSize != 0) {
                partCount++;
            }

            // 儲存已上傳分區的ETag
            List<PartETag> partETags = new ArrayList<>();

            // 遍曆上傳分區
            for (int i = 0; i < partCount; i++) {
                long startPos = i * partSize;
                long curPartSize = (i + 1 == partCount) ? (fileLength - startPos) : partSize;

                // 建立分區上傳請求
                UploadPartRequest uploadPartRequest = new UploadPartRequest();
                uploadPartRequest.setBucketName(bucketName);
                uploadPartRequest.setKey(objectName);
                uploadPartRequest.setUploadId(uploadId);
                uploadPartRequest.setPartNumber(i + 1);
                uploadPartRequest.setPartSize(curPartSize);

                // 讀取檔案分區並上傳
                try (InputStream instream = new FileInputStream(file)) {
                    instream.skip(startPos);
                    uploadPartRequest.setInputStream(instream);

                    UploadPartResult uploadPartResult = ossClient.uploadPart(uploadPartRequest);
                    partETags.add(uploadPartResult.getPartETag());

                    System.out.printf("上傳分區 %d/%d 成功,ETag: %s\n",
                            i + 1, partCount, uploadPartResult.getPartETag().getETag());
                }
            }

            // 步驟3:完成分區上傳
            CompleteMultipartUploadRequest completeRequest = new CompleteMultipartUploadRequest(
                    bucketName, objectName, uploadId, partETags);
            CompleteMultipartUploadResult completeResult = ossClient.completeMultipartUpload(completeRequest);

            System.out.printf("完成分區上傳,ETag: %s\n", completeResult.getETag());

        } catch (Exception e) {
            System.out.printf("錯誤: %s\n", e.getMessage());
            e.printStackTrace();
        } finally {
            // 關閉用戶端串連
            ossClient.shutdown();
        }
    }
}

Python SDK V2

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# OSS Python SDK V2 分區上傳樣本
# 實現大檔案的分區上傳功能

import alibabacloud_oss_v2 as oss
import os

def main():
    # 從環境變數擷取訪問憑證
    credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()

    # 載入SDK的預設配置
    config = oss.config.load_default()
    config.credentials_provider = credentials_provider

    # 設定OSS地區和Endpoint
    config.region = "cn-hangzhou"
    config.endpoint = "oss-cn-hangzhou.aliyuncs.com"

    # 初始化OSS用戶端
    client = oss.Client(config)

    # 配置Bucket和檔案資訊
    bucket = "example-bucket"
    key = "dest.jpg"
    file_path = "dest.jpg"

    try:
        # 步驟1:初始化分區上傳
        initiate_result = client.initiate_multipart_upload(
            oss.InitiateMultipartUploadRequest(
                bucket=bucket,
                key=key
            ))

        upload_id = initiate_result.upload_id
        print(f"初始化分區上傳成功,狀態代碼:{initiate_result.status_code}, "
              f"請求ID:{initiate_result.request_id}, 上傳ID:{upload_id}")

        # 步驟2:上傳分區
        file_size = os.path.getsize(file_path)
        part_size = 100 * 1024  # 每個分區100KB
        part_number = 1
        upload_parts = []
        offset = 0

        with open(file_path, 'rb') as f:
            while offset < file_size:
                # 計算當前分區大小
                current_part_size = min(part_size, file_size - offset)
                
                # 讀取分區資料
                f.seek(offset)
                part_data = f.read(current_part_size)

                # 上傳分區
                part_result = client.upload_part(
                    oss.UploadPartRequest(
                        bucket=bucket,
                        key=key,
                        upload_id=upload_id,
                        part_number=part_number,
                        body=part_data
                    ))

                print(f"狀態代碼: {part_result.status_code}, 請求ID: {part_result.request_id}, "
                      f"分區號: {part_number}, ETag: {part_result.etag}")

                # 記錄已上傳的分區資訊
                upload_parts.append(oss.UploadPart(
                    part_number=part_number,
                    etag=part_result.etag
                ))

                offset += current_part_size
                part_number += 1

        # 步驟3:完成分區上傳
        upload_parts.sort(key=lambda p: p.part_number)

        complete_result = client.complete_multipart_upload(
            oss.CompleteMultipartUploadRequest(
                bucket=bucket,
                key=key,
                upload_id=upload_id,
                complete_multipart_upload=oss.CompleteMultipartUpload(
                    parts=upload_parts
                )
            ))

        print(f"完成分區上傳,狀態代碼:{complete_result.status_code}, "
              f"請求ID:{complete_result.request_id}, "
              f"Bucket:{complete_result.bucket}, "
              f"Key:{complete_result.key}, "
              f"位置:{complete_result.location}, "
              f"ETag:{complete_result.etag}")

    except Exception as e:
        print(f"錯誤: {e}")
        raise

if __name__ == "__main__":
    main()

Python SDK V1

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# OSS Python SDK V1 分區上傳樣本
# 實現大檔案的分區上傳功能

import os
import oss2
from oss2.credentials import EnvironmentVariableCredentialsProvider
from oss2 import SizedFileAdapter
from oss2.models import PartInfo

def main():
    # 從環境變數擷取訪問憑證
    auth = oss2.ProviderAuth(EnvironmentVariableCredentialsProvider())

    # 設定OSS地區和Endpoint
    region = "cn-hangzhou"
    endpoint = "oss-cn-hangzhou.aliyuncs.com"

    # 配置Bucket和檔案資訊
    bucket_name = "example-bucket"
    key = "dest.jpg"
    file_path = "dest.jpg"

    # 初始化OSS Bucket
    bucket = oss2.Bucket(auth, endpoint, bucket_name, region=region)

    try:
        # 步驟1:初始化分區上傳
        upload_id = bucket.init_multipart_upload(key).upload_id
        print(f"初始化分區上傳成功,上傳ID: {upload_id}")

        # 步驟2:上傳分區
        file_size = os.path.getsize(file_path)
        part_size = 100 * 1024  # 每個分區100KB
        part_number = 1
        parts = []
        offset = 0

        with open(file_path, 'rb') as fileobj:
            while offset < file_size:
                # 計算當前分區大小
                current_part_size = min(part_size, file_size - offset)

                # 上傳分區
                result = bucket.upload_part(
                    key,
                    upload_id,
                    part_number,
                    SizedFileAdapter(fileobj, current_part_size)
                )

                print(f"分區號: {part_number}, ETag: {result.etag}")

                # 記錄已上傳的分區資訊
                parts.append(PartInfo(part_number, result.etag))

                offset += current_part_size
                part_number += 1

        # 步驟3:完成分區上傳
        result = bucket.complete_multipart_upload(key, upload_id, parts)
        print(f"完成分區上傳,ETag: {result.etag}")

    except Exception as e:
        print(f"錯誤: {e}")
        raise

if __name__ == "__main__":
    main()

Go SDK V2

package main

// OSS Go SDK V2 分區上傳樣本
// 實現大檔案的分區上傳功能

import (
	"context"
	"fmt"
	"io"
	"os"

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

func main() {
	// 從環境變數擷取訪問憑證
	// 配置OSS用戶端,設定憑證提供者和Endpoint
	config := oss.LoadDefaultConfig().
		WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
		WithRegion("cn-hangzhou").
		WithEndpoint("oss-cn-hangzhou.aliyuncs.com")

	// 初始化OSS用戶端
	client := oss.NewClient(config)

	// 配置Bucket和檔案資訊
	bucket := "example-bucket"
	key := "dest.jpg"
	filePath := "dest.jpg"

	// 步驟1:初始化分區上傳
	initResult, err := client.InitiateMultipartUpload(context.TODO(), &oss.InitiateMultipartUploadRequest{
		Bucket: oss.Ptr(bucket),
		Key:    oss.Ptr(key),
	})
	if err != nil {
		fmt.Printf("錯誤: %v\n", err)
		return
	}

	uploadId := *initResult.UploadId
	fmt.Printf("初始化分區上傳成功,上傳ID: %s\n", uploadId)

	// 步驟2:上傳分區
	file, err := os.Open(filePath)
	if err != nil {
		fmt.Printf("錯誤: %v\n", err)
		return
	}
	defer file.Close()

	fileInfo, err := file.Stat()
	if err != nil {
		fmt.Printf("錯誤: %v\n", err)
		return
	}

	fileSize := fileInfo.Size()
	partSize := int64(100 * 1024) // 每個分區100KB
	partNumber := int32(1)
	var parts []oss.UploadPart

	for offset := int64(0); offset < fileSize; offset += partSize {
		// 計算當前分區大小
		currentPartSize := partSize
		if offset+partSize > fileSize {
			currentPartSize = fileSize - offset
		}

		// 讀取分區資料
		file.Seek(offset, 0)
		partData := io.LimitReader(file, currentPartSize)

		// 上傳分區
		partResult, err := client.UploadPart(context.TODO(), &oss.UploadPartRequest{
			Bucket:     oss.Ptr(bucket),
			Key:        oss.Ptr(key),
			UploadId:   oss.Ptr(uploadId),
			PartNumber: partNumber,
			Body:       partData,
		})
		if err != nil {
			fmt.Printf("錯誤: %v\n", err)
			return
		}

		fmt.Printf("分區號: %d, ETag: %s\n", partNumber, *partResult.ETag)

		// 記錄已上傳的分區資訊
		parts = append(parts, oss.UploadPart{
			PartNumber: partNumber,
			ETag:       partResult.ETag,
		})

		partNumber++
	}

	// 步驟3:完成分區上傳
	completeResult, err := client.CompleteMultipartUpload(context.TODO(), &oss.CompleteMultipartUploadRequest{
		Bucket:   oss.Ptr(bucket),
		Key:      oss.Ptr(key),
		UploadId: oss.Ptr(uploadId),
		CompleteMultipartUpload: &oss.CompleteMultipartUpload{
			Parts: parts,
		},
	})
	if err != nil {
		fmt.Printf("錯誤: %v\n", err)
		return
	}

	fmt.Printf("完成分區上傳,Bucket: %s, Key: %s, Location: %s, ETag: %s\n",
		*completeResult.Bucket, *completeResult.Key, *completeResult.Location, *completeResult.ETag)
}

Go SDK V1

package main

// OSS Go SDK V1 分區上傳樣本
// 實現大檔案的分區上傳功能

import (
	"fmt"
	"os"

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

func main() {
	// 從環境變數擷取訪問憑證
	provider, _ := oss.NewEnvironmentVariableCredentialsProvider()

	// 建立OSS用戶端執行個體
	client, _ := oss.New(
		"oss-cn-hangzhou.aliyuncs.com",
		"",
		"",
		oss.SetCredentialsProvider(&provider),
		oss.AuthVersion(oss.AuthV4),
		oss.Region("cn-hangzhou"),
	)

	// 擷取Bucket對象
	bucket, _ := client.Bucket("example-bucket")

	// 設定檔資訊
	key := "dest.jpg"
	filePath := "dest.jpg"

	// 步驟1:初始化分區上傳
	imur, err := bucket.InitiateMultipartUpload(key)
	if err != nil {
		fmt.Printf("錯誤: %v\n", err)
		return
	}

	fmt.Printf("初始化分區上傳成功,上傳ID: %s\n", imur.UploadID)

	// 步驟2:上傳分區
	file, err := os.Open(filePath)
	if err != nil {
		fmt.Printf("錯誤: %v\n", err)
		return
	}
	defer file.Close()

	fileInfo, err := file.Stat()
	if err != nil {
		fmt.Printf("錯誤: %v\n", err)
		return
	}

	fileSize := fileInfo.Size()
	partSize := int64(100 * 1024) // 每個分區100KB

	// 將檔案分區
	chunks, err := oss.SplitFileByPartSize(filePath, partSize)
	if err != nil {
		fmt.Printf("錯誤: %v\n", err)
		return
	}

	var parts []oss.UploadPart
	for _, chunk := range chunks {
		part, err := bucket.UploadPart(imur, file, chunk.Size, chunk.Number)
		if err != nil {
			fmt.Printf("錯誤: %v\n", err)
			return
		}

		fmt.Printf("分區號: %d, ETag: %s\n", chunk.Number, part.ETag)
		parts = append(parts, part)
	}

	// 步驟3:完成分區上傳
	_, err = bucket.CompleteMultipartUpload(imur, parts)
	if err != nil {
		fmt.Printf("錯誤: %v\n", err)
		return
	}

	fmt.Printf("完成分區上傳,檔案大小: %d 位元組\n", fileSize)
}

清理片段檔案

重要

根據策略調整,為提升OSS服務的合規性和安全性,自2025年3月20日起,新開通OSS服務的使用者在中國內地地區的Bucket將無法通過預設外網網域名稱調用資料操作類API(如上傳、下載檔案),需通過自訂網域名(CNAME)方式訪問OSS服務。使用HTTPS協議訪問(如控制台)時,還需為自訂網域名配置SSL認證

分區上傳過程意外中斷且未調用AbortMultipartUpload介面時,已上傳的分區會作為片段檔案保留在Bucket中並持續產生儲存費用。及時清理這些片段檔案可避免不必要的儲存成本。

通過控制台

  1. 前往Bucket列表,單擊目標Bucket。

  2. 檔案清單單擊片段管理,查看並刪除片段檔案。

通過生命週期規則

配置生命週期規則可實現對到期片段的自動清理,減少手動維護工作量並防止遺漏。具體操作參見通過生命週期規則清理到期片段

通過工具

  • 圖形化管理工具ossbrowser

    在Bucket的檔案清單頁面單擊檔案片段,查看並刪除片段檔案。

  • 命令列工具ossutil

    使用abort-multipart-upload命令取消分區上傳任務並刪除對應的分區資料。命令樣本如下:

    ossutil api abort-multipart-upload --bucket example-bucket --key dest.jpg --upload-id D9F4****************************

通過SDK

通過調用AbortMultipartUpload介面取消分區上傳任務並刪除對應的分區資料。以下為常見語言的SDK取消分區上傳任務程式碼範例,更多語言的使用樣本請參見SDK參考中對應語言的範例程式碼。

運行代碼前需安裝對應語言的SDK並配置訪問憑證環境變數,使用RAM使用者或RAM角色時還需參考API和許可權說明進行介面授權。

Java SDK V2

import com.aliyun.sdk.service.oss2.OSSClient;
import com.aliyun.sdk.service.oss2.credentials.CredentialsProvider;
import com.aliyun.sdk.service.oss2.credentials.StaticCredentialsProvider;
import com.aliyun.sdk.service.oss2.models.AbortMultipartUploadRequest;
import com.aliyun.sdk.service.oss2.models.AbortMultipartUploadResult;

/**
 * OSS取消分區上傳樣本
 * 示範如何取消一個分區上傳任務
 */
public class AbortMultipartUpload {

    public static void main(String[] args) {
        // 從環境變數擷取訪問憑證
        String accessKeyId = System.getenv("OSS_ACCESS_KEY_ID");
        String accessKeySecret = System.getenv("OSS_ACCESS_KEY_SECRET");

        // 設定OSS地區和Endpoint
        String region = "cn-hangzhou";
        String endpoint = "oss-cn-hangzhou.aliyuncs.com";

        // 配置Bucket和檔案資訊
        String bucket = "example-bucket";
        String key = "dest.jpg";
        String uploadId = "D9F4****************************";

        // 建立憑證提供者
        CredentialsProvider provider = new StaticCredentialsProvider(accessKeyId, accessKeySecret);

        // 初始化OSS用戶端
        OSSClient client = OSSClient.newBuilder()
                .credentialsProvider(provider)
                .region(region)
                .endpoint(endpoint)
                .build();

        try {
            // 取消分區上傳
            AbortMultipartUploadResult result = client.abortMultipartUpload(
                    AbortMultipartUploadRequest.newBuilder()
                            .bucket(bucket)
                            .key(key)
                            .uploadId(uploadId)
                            .build());

            System.out.printf("取消分區上傳成功,狀態代碼: %d, 請求ID: %s\n",
                    result.statusCode(), result.requestId());

        } catch (Exception e) {
            System.out.printf("錯誤: %s\n", e.getMessage());
            e.printStackTrace();
        } finally {
            // 關閉用戶端串連
            try {
                client.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}

Java SDK V1

import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.common.comm.SignVersion;
import com.aliyun.oss.model.*;

/**
 * OSS取消分區上傳樣本(V1 SDK)
 * 示範如何取消一個分區上傳任務
 */
public class AbortMultipartUpload {

    public static void main(String[] args) {
        // 從環境變數擷取訪問憑證
        String accessKeyId = System.getenv("OSS_ACCESS_KEY_ID");
        String accessKeySecret = System.getenv("OSS_ACCESS_KEY_SECRET");

        // 設定OSS地區和Endpoint
        String region = "cn-hangzhou";
        String endpoint = "oss-cn-hangzhou.aliyuncs.com";

        // 配置Bucket和檔案資訊
        String bucketName = "example-bucket";
        String objectName = "dest.jpg";
        String uploadId = "D9F4****************************";

        // 建立憑證提供者
        DefaultCredentialProvider provider = new DefaultCredentialProvider(accessKeyId, accessKeySecret);

        // 配置用戶端參數
        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);

        // 初始化OSS用戶端
        OSS ossClient = OSSClientBuilder.create()
                .credentialsProvider(provider)
                .clientConfiguration(clientBuilderConfiguration)
                .region(region)
                .endpoint(endpoint)
                .build();

        try {
            // 取消分區上傳
            AbortMultipartUploadRequest abortMultipartUploadRequest =
                    new AbortMultipartUploadRequest(bucketName, objectName, uploadId);
            ossClient.abortMultipartUpload(abortMultipartUploadRequest);

            System.out.printf("取消分區上傳成功,上傳ID: %s\n", uploadId);

        } catch (Exception e) {
            System.out.printf("錯誤: %s\n", e.getMessage());
            e.printStackTrace();
        } finally {
            // 關閉用戶端串連
            ossClient.shutdown();
        }
    }
}

Python SDK V2

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# OSS Python SDK V2 取消分區上傳樣本
# 取消分區上傳任務並刪除已上傳的分區

import alibabacloud_oss_v2 as oss

def main():
    # 從環境變數擷取訪問憑證
    credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()

    # 載入SDK的預設配置
    config = oss.config.load_default()
    config.credentials_provider = credentials_provider

    # 設定OSS地區和Endpoint
    config.region = "cn-hangzhou"
    config.endpoint = "oss-cn-hangzhou.aliyuncs.com"

    # 初始化OSS用戶端
    client = oss.Client(config)

    # 配置Bucket和檔案資訊
    bucket = "example-bucket"
    key = "dest.jpg"
    upload_id = "D9F4****************************"

    # 取消分區上傳
    result = client.abort_multipart_upload(
        oss.AbortMultipartUploadRequest(
            bucket=bucket,
            key=key,
            upload_id=upload_id
        ))

    print(f"取消分區上傳成功,狀態代碼: {result.status_code}, 請求ID: {result.request_id}")

if __name__ == "__main__":
    main()

Python SDK V1

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# OSS Python SDK V1 取消分區上傳樣本

import oss2
from oss2.credentials import EnvironmentVariableCredentialsProvider

def main():
    # 從環境變數中擷取訪問憑證
    auth = oss2.ProviderAuthV4(EnvironmentVariableCredentialsProvider())
    
    # 設定OSS地區和Endpoint
    region = "cn-hangzhou"
    endpoint = "https://oss-cn-hangzhou.aliyuncs.com"
    
    # 配置Bucket和檔案資訊
    bucket_name = "example-bucket"
    key = "dest.jpg"
    upload_id = "D9F4****************************"
    
    # 初始化OSS用戶端
    bucket = oss2.Bucket(auth, endpoint, bucket_name, region=region)
    
    # 取消分區上傳
    bucket.abort_multipart_upload(key, upload_id)
    
    print(f"取消分區上傳成功,上傳ID: {upload_id}")

if __name__ == "__main__":
    main()

Go SDK V2

package main

// OSS Go SDK V2 取消分區上傳樣本

import (
	"context"
	"fmt"

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

func main() {
	// 從環境變數擷取訪問憑證
	// 配置OSS用戶端,設定憑證提供者和Endpoint
	config := oss.LoadDefaultConfig().
		WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
		WithRegion("cn-hangzhou").
		WithEndpoint("oss-cn-hangzhou.aliyuncs.com")

	// 初始化OSS用戶端
	client := oss.NewClient(config)

	// 配置Bucket和檔案資訊
	bucket := "example-bucket"
	key := "dest.jpg"
	uploadId := "D9F4****************************"

	// 取消分區上傳
	client.AbortMultipartUpload(context.TODO(), &oss.AbortMultipartUploadRequest{
		Bucket:   oss.Ptr(bucket),
		Key:      oss.Ptr(key),
		UploadId: oss.Ptr(uploadId),
	})

	fmt.Printf("取消分區上傳成功,上傳ID: %s\n", uploadId)
}

Go SDK V1

package main

// OSS Go SDK V1 取消分區上傳樣本

import (
	"fmt"

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

func main() {
	// 從環境變數擷取訪問憑證
	provider, _ := oss.NewEnvironmentVariableCredentialsProvider()

	// 建立OSS用戶端執行個體
	client, _ := oss.New(
		"oss-cn-hangzhou.aliyuncs.com",
		"",
		"",
		oss.SetCredentialsProvider(&provider),
		oss.AuthVersion(oss.AuthV4),
		oss.Region("cn-hangzhou"),
	)

	// 擷取Bucket對象
	bucket, _ := client.Bucket("example-bucket")

	// 設定檔資訊
	key := "dest.jpg"
	uploadId := "D9F4****************************"

	// 建立InitiateMultipartUploadResult對象
	imur := oss.InitiateMultipartUploadResult{
		UploadID: uploadId,
		Key:      key,
	}

	// 取消分區上傳
	bucket.AbortMultipartUpload(imur)

	fmt.Printf("取消分區上傳成功,上傳ID: %s\n", uploadId)
}

應用於生產環境

最佳實務

  • 效能最佳化:提升上傳速度和穩定性

    • 合理控制並發數量:根據網路頻寬和裝置負載確定合理的並發分區數量。過多的並發串連會增加系統負載和網路擁塞,過少則無法充分利用網路資源。

    • 避免順序首碼命名:上傳大量檔案時避免使用順序首碼(如時間戳記開頭),防止請求集中在特定分區造成熱點問題,影響整體上傳效能。詳見OSS效能最佳實務

  • 可靠性保障:實現斷點續傳

    分區上傳任務無到期時間限制,支援暫停和恢複操作。利用Upload ID作為任務標識符,當單個分區上傳失敗時,僅需重傳該分區,避免從頭開始上傳整個檔案,大幅提升傳輸效率。

  • 成本最佳化:最佳化深度冷歸檔上傳策略

    對於需要儲存到深度冷歸檔的大量檔案,建議先上傳為標準儲存類型,再通過生命週期規則自動轉換儲存類型,避免直接上傳產生高額的PUT請求費用。

風險防範

  • 資料安全:防止檔案覆蓋

    在上傳請求header中設定x-oss-forbid-overwrite參數為true,防止覆蓋同名檔案造成資料丟失。也可開啟版本控制功能保留歷史版本。

配額與限制

限制項

說明

單個檔案的大小

不超過48.8TB

分區數量

1~10,000個

單個分區大小

最小值為100KB,最大值為5GB。最後一個分區的大小允許小於100KB。

單次ListParts請求返回的分區最大數量

1,000個

單次ListMultipartUploads請求返回的分區上傳事件最大數量

1,000個

計費說明

分區上傳過程中不同介面產生相應的計費項目如下表所示。詳細的計費說明請參見請求費用儲存費用

API

計費項目

說明

InitiateMultipartUpload

PUT 類型請求

根據成功的請求次數計算請求費用。

UploadPart

PUT 類型請求

根據成功的請求次數計算請求費用。

儲存費用

根據分區的儲存類型(與對象檔案類型一致)、實際大小和儲存時間長度收取儲存費用。無最小計量單位限制,被刪除或合并為完整的對象檔案後停止計費。

UploadPartCopy

PUT 類型請求

根據成功的請求次數計算請求費用。

CompleteMultipartUpload

PUT 類型請求

根據成功的請求次數計算請求費用。

儲存費用

根據對象檔案的儲存類型、大小和時間長度收取儲存費用。

AbortMultipartUpload

PUT 類型請求

根據成功的請求次數計算請求費用。

重要
  • 在中國內地各地區,通過生命週期規則刪除低頻訪問、歸檔、冷歸檔類型片段的PUT類請求費用高於刪除標準儲存類型片段的PUT類請求費用;通過生命週期規則刪除深度冷Archive Storage類型片段,不收取PUT類請求費用。

  • 在中國香港以及海外地區,通過生命週期規則刪除各儲存類型片段時不收取PUT類請求費用。

ListMultipartUploads

PUT 類型請求

根據成功的請求次數計算請求費用。

ListParts

PUT 類型請求

根據成功的請求次數計算請求費用。

API和許可權說明

阿里雲主帳號預設擁有全部API的操作許可權。RAM使用者或RAM角色使用分區上傳功能需根據具體操作的API授予相應許可權。更多資訊請參見RAM PolicyRAM Policy常見樣本

API

Action

說明

InitiateMultipartUpload

oss:PutObject

初始化分區上傳任務。

oss:PutObjectTagging

初始化分區上傳任務時,如果通過x-oss-tagging指定對象檔案的標籤,則需要此操作的許可權。

kms:GenerateDataKey

上傳對象檔案時,如果對象檔案的中繼資料套件含X-Oss-Server-Side-Encryption: KMS,則需要這兩個操作的許可權。

kms:Decrypt

UploadPart

oss:PutObject

上傳分區。

UploadPartCopy

oss:GetObject

從一個已存在的對象檔案中拷貝資料來上傳一個分區時,需要讀取來源物件檔案的許可權。

oss:PutObject

從一個已存在的對象檔案中拷貝資料來上傳一個分區時,需要寫入目標對象檔案的許可權。

oss:GetObjectVersion

從一個已存在的對象檔案中拷貝資料來上傳一個分區時,如果通過versionId指定對象檔案的版本,需要讀取來源物件檔案的指定版本的許可權。

CompleteMultipartUpload

oss:PutObject

將分區合并為對象檔案。

oss:PutObjectTagging

將分區合并為對象檔案時,如果通過x-oss-tagging指定對象檔案的標籤,則需要此操作的許可權。

AbortMultipartUpload

oss:AbortMultipartUpload

取消分區上傳事件並刪除對應的分區資料。

ListMultipartUploads

oss:ListMultipartUploads

列舉所有執行中的分區上傳事件,即已經初始化但尚未完成或者尚未被中止的分區上傳事件。

ListParts

oss:ListParts

列舉指定Upload ID所屬的所有已經上傳成功的分區。