大檔案上傳面臨網路中斷風險和傳輸時間過長的挑戰。分區上傳通過將檔案分割為多個小分區並發傳輸,提供斷點續傳能力和傳輸效能最佳化,有效應對網路不穩定環境下的檔案傳輸需求。
工作原理
分區上傳將大檔案分割為多個小分區進行獨立處理,各分區獨立傳輸和校正,單個分區失敗時僅需重傳該分區,避免重新上傳整個檔案。分區上傳使用Upload ID作為任務標識符,確保所有分區正確歸屬於同一個上傳任務。核心流程分為三個步驟:
初始化上傳任務:調用InitiateMultipartUpload介面建立分區上傳任務,擷取唯一的Upload ID作為後續操作的標識符。
上傳檔案分區資料:將檔案切分為多個分區(Part)並發上傳,每個分區大小在100KB到5GB之間,支援斷點續傳。
合并分區完成上傳:調用CompleteMultipartUpload介面將所有分區按序號合并為完整的對象檔案。
實現大檔案分區上傳
根據應用情境和技術要求,可選擇圖形化工具、命令列工具或SDK來實現分區上傳功能。
OSS控制台暫不支援分區上傳操作。
支援上傳加密的壓縮檔,但不支援上傳目錄。
通過工具自動分區
對於日常開發、測試、營運或手動上傳情境,推薦使用圖形化或命令列工具,工具會自動處理分區邏輯,操作便捷。
圖形化管理工具ossbrowser
使用圖形化管理工具ossbrowser 2.0上傳檔案時,預設啟用分區上傳機制,並提供可視化的上傳進度和狀態監控。
命令列工具ossutil
使用命令列工具ossutil 2.0的cp命令上傳檔案時,工具會自動對超過100MiB的檔案啟用分區上傳,提高大檔案上傳的成功率和傳輸效率。如需手動控制分區上傳過程,可組合使用initiate-multipart-upload、upload-part和complete-multipart-upload命令。
ossutil cp example.zip oss://example-bucket
通過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)
}
清理片段檔案
分區上傳過程意外中斷且未調用AbortMultipartUpload介面時,已上傳的分區會作為片段檔案保留在Bucket中並持續產生儲存費用。及時清理這些片段檔案可避免不必要的儲存成本。
通過控制台
前往Bucket列表,單擊目標Bucket。
在檔案清單單擊片段管理,查看並刪除片段檔案。
通過生命週期規則
配置生命週期規則可實現對到期片段的自動清理,減少手動維護工作量並防止遺漏。具體操作參見通過生命週期規則清理到期片段。
通過工具
圖形化管理工具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 類型請求 | 根據成功的請求次數計算請求費用。 重要
|
ListMultipartUploads | PUT 類型請求 | 根據成功的請求次數計算請求費用。 |
ListParts | PUT 類型請求 | 根據成功的請求次數計算請求費用。 |
API和許可權說明
阿里雲主帳號預設擁有全部API的操作許可權。RAM使用者或RAM角色使用分區上傳功能需根據具體操作的API授予相應許可權。更多資訊請參見RAM Policy和RAM Policy常見樣本。
API | Action | 說明 |
InitiateMultipartUpload |
| 初始化分區上傳任務。 |
| 初始化分區上傳任務時,如果通過x-oss-tagging指定對象檔案的標籤,則需要此操作的許可權。 | |
| 上傳對象檔案時,如果對象檔案的中繼資料套件含X-Oss-Server-Side-Encryption: KMS,則需要這兩個操作的許可權。 | |
| ||
UploadPart |
| 上傳分區。 |
UploadPartCopy |
| 從一個已存在的對象檔案中拷貝資料來上傳一個分區時,需要讀取來源物件檔案的許可權。 |
| 從一個已存在的對象檔案中拷貝資料來上傳一個分區時,需要寫入目標對象檔案的許可權。 | |
| 從一個已存在的對象檔案中拷貝資料來上傳一個分區時,如果通過versionId指定對象檔案的版本,需要讀取來源物件檔案的指定版本的許可權。 | |
CompleteMultipartUpload |
| 將分區合并為對象檔案。 |
| 將分區合并為對象檔案時,如果通過x-oss-tagging指定對象檔案的標籤,則需要此操作的許可權。 | |
AbortMultipartUpload |
| 取消分區上傳事件並刪除對應的分區資料。 |
ListMultipartUploads |
| 列舉所有執行中的分區上傳事件,即已經初始化但尚未完成或者尚未被中止的分區上傳事件。 |
ListParts |
| 列舉指定Upload ID所屬的所有已經上傳成功的分區。 |