分块上传
最近更新时间: 2025-02-18 16:02:00
适用场景
分块上传适合于在弱网络或高带宽环境下上传较大的对象。COS 的控制台和 SDK 会协助您将单个对象切成一组分块并完成上传,您也可以自行切分对象并分别调用 API 上传各个分块。使用分块上传有一些优势:
- 在弱网络环境中,使用较小的分块可以将网络失败导致的中断影响降低,实现对象续传。
- 在高带宽环境中,并发上传对象分块能充分利用网络带宽,乱序上传并不影响最终组合对象。
- 使用分块上传,您可以随时暂停和恢复单个大对象的上传。除非发起终止操作,所有未完成的对象将可随时继续上传。
- 分块上传也适用于在未知对象总大小的情况下上传对象,您可以先发起上传,再组合对象以获得完整大小。
上传时,这组分块将会按连续的序号编号,您可以独立上传或者按照任意顺序上传各个分块,最终 COS 将会根据分块编号顺序重新组合出该对象。任意分块传输失败,都可以重新传输当前分块,不会影响其他分块和内容完整性。一般在弱网络环境中,当单个对象大于 20 MB 可优先考虑分块上传,在大带宽环境中可将超过 100 MB 的对象进行分块上传。
使用方法
使用 REST API
您可以直接使用 REST API 发起一个分块上传的请求,可参考以下 API 文档部分:
- Initiate Multipart Upload
- Complete Multipart Upload
- Upload Part
- Abort Multipart Upload
使用 Java SDK
对象存储 COS 的 Java SDK 中提供了此方法,可参考 Java SDK 接口文档 PUT object 中的分块文件上传部分。
步骤说明
- 初始化客户端 cosclient。
- 使用 initiateMultipartUpload 初始化分块上传获取一个新的 uploadid,或者调用 listMultipartUploads 获取之前还未完成的分块上传,得到 uploadid。
- 已上传的分块可使用 listParts 进行获取,未上传的分块使用 uploadPart 上传分块数据, 或者 copyPart 选择从另外一个文件 copy 分块到目前文件。以此达到断点续传的功能,如果对已上传的分块再次调用 uploadPart 或者 copyPart 则会覆盖已上传的分块数据。
- 使用 completeMultipartUpload 完成分块上传或者调用 abortMultipartUpload 终止分块上传。
代码示例
InitiateMultipartUploadRequest
是初始化分块上传的请求,包含了分快上传的路径,存储类型等信息。通过调用 initiateMultipartUpload 可获得一个新的分快上传 ID。
// 1 初始化用户身份信息(secretId, secretKey)
COSCredentials cred = new BasicCOSCredentials("AKIDXXXXXXXX", "1A2Z3YYYYYYYYYY");
// 2 设置bucket的区域, COS地域的简称请参照 /document/product/436/6224
ClientConfig clientConfig = new ClientConfig(new Region("ap-beijing-1"));
// 3 生成cos客户端
COSClient cosclient = new COSClient(cred, clientConfig);
// bucket名需包含appid
String bucketName = "mybucket-1251668577";
String key = "aaa/bbb.txt";
InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(bucketName, key);
// 设置存储类型, 默认是标准(Standard), 低频(standard_ia), 近线(nearline)
request.setStorageClass(StorageClass.Standard_IA);
try {
InitiateMultipartUploadResult initResult = cosclient.initiateMultipartUpload(request);
// 获取uploadid
String uploadId = initResult.getUploadId();
} catch (CosServiceException e) {
e.printStackTrace();
} catch (CosClientException e) {
e.printStackTrace();
}
cosclient.shutdown();
UploadPartRequest
是分块上传请求,包含了要上传的数据,分块号。通过调用uploadPart 上传分块,并获取分块的 partEtag。
// 1 初始化用户身份信息(secretId, secretKey)
COSCredentials cred = new BasicCOSCredentials("AKIDXXXXXXXX", "1A2Z3YYYYYYYYYY");
// 2 设置bucket的区域, COS地域的简称请参照 /document/product/436/6224
ClientConfig clientConfig = new ClientConfig(new Region("ap-beijing-1"));
// 3 生成cos客户端
COSClient cosclient = new COSClient(cred, clientConfig);
// bucket名需包含appid
String bucketName = "mybucket-1251668577";
String key = "aaa/bbb.txt";
// uploadid(通过initiateMultipartUpload或者ListMultipartUploads获取)
String uploadId = "1512380198aecfed004aeaaca195d08232f718f7b52a91b8f6e9d36c7dfead2b3d1c917a6f";
// 生成要上传的数据, 这里初始化一个1M的数据
byte data[] = new byte[1024 * 1024];
UploadPartRequest uploadPartRequest = new UploadPartRequest();
uploadPartRequest.setBucketName(bucketName);
uploadPartRequest.setKey(key);
uploadPartRequest.setUploadId(uploadId);
// 设置分块的数据来源输入流
uploadPartRequest.setInputStream(new ByteArrayInputStream(data));
// 设置分块的长度
uploadPartRequest.setPartSize(data.length); // 设置数据长度
uploadPartRequest.setPartNumber(10); // 假设要上传的part编号是10
try {
UploadPartResult uploadPartResult = cosclient.uploadPart(uploadPartRequest);
PartETag partETag = uploadPartResult.getPartETag();
} catch (CosServiceException e) {
e.printStackTrace();
} catch (CosClientException e) {
e.printStackTrace();
}
cosclient.shutdown();
CompleteMultipartUploadRequest
是完成分块请求,需要传入之前上传的所有分块的partEtag。通过调用completeMultipartUpload完成分块上传。示例代码如下:
// 1 初始化用户身份信息(secretId, secretKey)
COSCredentials cred = new BasicCOSCredentials("AKIDXXXXXXXX", "1A2Z3YYYYYYYYYY");
// 2 设置bucket的区域, COS地域的简称请参照 /document/product/436/6224
ClientConfig clientConfig = new ClientConfig(new Region("ap-beijing-1"));
// 3 生成cos客户端
COSClient cosclient = new COSClient(cred, clientConfig);
// bucket名需包含appid
String bucketName = "mybucket-1251668577";
String key = "aaa/bbb.txt";
// uploadid(通过initiateMultipartUpload或者ListMultipartUploads获取)
String uploadId = "1512380198aecfed004aeaaca195d08232f718f7b52a91b8f6e9d36c7dfead2b3d1c917a6f";
// 这里初始化一个空的队列, 用于保存已上传的分片信息, 代码不能直接运行, 需要通过之前的uploadpart或者list parts的结果获取,加入到partEtags队列中
List<PartETag> partETags = new LinkedList<>();
// 分片上传结束后,调用complete完成分片上传
CompleteMultipartUploadRequest completeMultipartUploadRequest =
new CompleteMultipartUploadRequest(bucketName, key, uploadId, partETags);
try {
CompleteMultipartUploadResult completeResult =
cosclient.completeMultipartUpload(completeMultipartUploadRequest);
String etag = completeResult.getETag();
} catch (CosServiceException e) {
e.printStackTrace();
} catch (CosClientException e) {
e.printStackTrace();
}
cosclient.shutdown();
AbortMultipartUploadRequest
是终止分块上传请求,用于终止一个未 complete 的分块上传,表示中断销毁之前已上传的分块。通过调用 abortMultipartUpload 终止分块上传请求,示例代码如下:
// 1 初始化用户身份信息(secretId, secretKey)
COSCredentials cred = new BasicCOSCredentials("AKIDXXXXXXXX", "1A2Z3YYYYYYYYYY");
// 2 设置bucket的区域, COS地域的简称请参照 /document/product/436/6224
ClientConfig clientConfig = new ClientConfig(new Region("ap-beijing-1"));
// 3 生成cos客户端
COSClient cosclient = new COSClient(cred, clientConfig);
// bucket名需包含appid
String bucketName = "mybucket-1251668577";
String key = "aaa/bbb.txt";
// uploadid(通过initiateMultipartUpload或者ListMultipartUploads获取)
String uploadId = "1512380198aecfed004aeaaca195d08232f718f7b52a91b8f6e9d36c7dfead2b3d1c917a6f";
AbortMultipartUploadRequest abortMultipartUploadRequest = new AbortMultipartUploadRequest(bucketName, key, uploadId);
try {
cosclient.abortMultipartUpload(abortMultipartUploadRequest);
} catch (CosServiceException e) {
e.printStackTrace();
} catch (CosClientException e) {
e.printStackTrace();
}
cosclient.shutdown();
ListPartsRequest
是列出已上传的分块的请求,可用于断点续传。通过调用 listParts 获取已上传的分块,示例代码如下:
// 1 初始化用户身份信息(secretId, secretKey)
COSCredentials cred = new BasicCOSCredentials("AKIDXXXXXXXX", "1A2Z3YYYYYYYYYY");
// 2 设置bucket的区域, COS地域的简称请参照 /document/product/436/6224
ClientConfig clientConfig = new ClientConfig(new Region("ap-beijing-1"));
// 3 生成cos客户端
COSClient cosclient = new COSClient(cred, clientConfig);
// bucket名需包含appid
String bucketName = "mybucket-1251668577";
String key = "aaa/bbb.txt";
// uploadid(通过initiateMultipartUpload或者ListMultipartUploads获取)
String uploadId = "1512380198aecfed004aeaaca195d08232f718f7b52a91b8f6e9d36c7dfead2b3d1c917a6f";
List<PartETag> partETags = new LinkedList<>(); // 用于保存已上传的分片信息
PartListing partListing = null;
ListPartsRequest listPartsRequest = new ListPartsRequest(bucketName, key, uploadId);
do {
try {
partListing = cosclient.listParts(listPartsRequest);
} catch (CosServiceException e) {
e.printStackTrace();
} catch (CosClientException e) {
e.printStackTrace();
}
for (PartSummary partSummary : partListing.getParts()) {
partETags.add(new PartETag(partSummary.getPartNumber(), partSummary.getETag()));
}
listPartsRequest.setPartNumberMarker(partListing.getNextPartNumberMarker());
} while (partListing.isTruncated());
cosclient.shutdown();
CopyPartResult
是分块 copy 的请求,表示该分块的数据来源于另外一个文件的某一部分。通过要拷贝的源文件的路径,bucket 信息,字节范围。调用 copyPart 可实现分块copy。示例代码如下所示:
// 1 初始化用户身份信息(secretId, secretKey)
COSCredentials cred = new BasicCOSCredentials("AKIDXXXXXXXX", "1A2Z3YYYYYYYYYY");
// 2 设置bucket的区域, COS地域的简称请参照 /document/product/436/6224
ClientConfig clientConfig = new ClientConfig(new Region("ap-beijing-1"));
// 3 生成cos客户端
COSClient cosclient = new COSClient(cred, clientConfig);
// bucket名需包含appid
String bucketName = "mybucket-1251668577";
String key = "aaa/bbb.txt";
// uploadid(通过initiateMultipartUpload或者ListMultipartUploads获取)
String uploadId = "1512380198aecfed004aeaaca195d08232f718f7b52a91b8f6e9d36c7dfead2b3d1c917a6f";
CopyPartRequest copyPartRequest = new CopyPartRequest();
// 要拷贝的源文件所在的region
copyPartRequest.setSourceBucketRegion(new Region("ap-beijing-1"));
// 要拷贝的源文件的bucket名称
copyPartRequest.setSourceBucketName(bucketName);
// 要拷贝的源文件的路径
copyPartRequest.setSourceKey("aaa/ccc.txt");
// 指定要拷贝的源文件的数据范围(类似content-range)
copyPartRequest.setFirstByte(0L);
copyPartRequest.setLastByte(1048575L);
// 目的bucket名称
copyPartRequest.setDestinationBucketName(bucketName);
// 目的路径名称
copyPartRequest.setDestinationKey(key);
// uploadid
copyPartRequest.setUploadId(uploadId);
try {
CopyPartResult copyPartResult = cosclient.copyPart(copyPartRequest);
PartETag partETag = copyPartResult.getPartETag();
} catch (CosServiceException e) {
e.printStackTrace();
} catch (CosClientException e) {
e.printStackTrace();
}
cosclient.shutdown();