大文件上传面临网络中断风险和传输时间过长的挑战。分片上传通过将文件分割为多个小分片并发传输,提供断点续传能力和传输性能优化,有效应对网络不稳定环境下的文件传输需求。
工作原理
分片上传将大文件分割为多个小分片进行独立处理,各分片独立传输和校验,单个分片失败时仅需重传该分片,避免重新上传整个文件。分片上传使用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所属的所有已经上传成功的分片。 |