分片上传

更新时间: 2020-04-24

目录

初始化分片

上传分片

合并分片

完整分片上传

中止分片上传

列举分片上传事件

本节介绍分片上传的相关功能。

分片上传(Multipart Upload)分为以下三个步骤:

  • 初始化分片。

    调用ossClient.initiateMultipartUpload方法返回OSS创建的全局唯一的uploadId。

  • 将文件进行分片,并上传分片。

    调用ossClient.uploadPart方法上传分片数据。

    • 对于同一个uploadId,分片号(partNumber)标识了该分片在整个文件内的相对位置。如果使用同一个分片号上传了新的数据,那么OSS上这个分片已有的数据将会被覆盖。
    • OSS将收到的分片数据的MD5值放在ETag头内返回给用户。
    • OSS计算上传数据的MD5值,并与SDK计算的MD5值比较,如果不一致则返回InvalidDigest错误码。
  • 合并分片。

    所有分片上传完成后,调用ossClient.completeMultipartUpload方法将所有分片合并成完整的文件。

初始化分片

以下代码用于初始化分片:

// Endpoint以华北三为例,其它Region请按实际情况填写
String endpoint = "oss.cn-north-3.inspurcloudoss.com";
String accessKey = "<yourAccessKey>";
String secretKey = "<yourSecretKey>";
String bucketName = "<yourBucketName>";
String key = "<yourObjectName>";

//创建OSSClient实例
OSSClientImpl ossClient = new OSSClientImpl(endpoint, accessKey, secretKey);

//初始化分片
InitiateMultipartUploadRequest initiateMultipartUploadRequest = new InitiateMultipartUploadRequest(bucketName, key);
InitiateMultipartUploadResult initiateMultipartUploadResult = ossClient.initiateMultipartUpload(initiateMultipartUploadRequest);
System.out.println("Initiating Multipart: " + initiateMultipartUploadResult);

上传分片

以下代码用于上传分片:

// Endpoint以华北三为例,其它Region请按实际情况填写
String endpoint = "oss.cn-north-3.inspurcloudoss.com";
String accessKey = "<yourAccessKey>";
String secretKey = "<yourSecretKey>";
String bucketName = "<yourBucketName>";
String key = "<yourObjectName>";

//创建OSSClient实例
OSSClientImpl ossClient = new OSSClientImpl(endpoint, accessKey, secretKey);

//上传碎片
//fileName需要是文件的物理路径
//objectUploadId表示文件的上传ID号,可以在初始化文件(ossClient.initiateMultipartUpload)的返回值得到
UploadPartRequest uploadPartRequest = new UploadPartRequest(bucketName, key, "<objectUploadId>", new File("<fileName>"));
UploadPartResult uploadPartResult = ossClient.uploadPart(uploadPartRequest);
System.out.println("Uploading part: " + uploadPartResult);

合并分片

以下代码用于合并分片:

// Endpoint以华北三为例,其它Region请按实际情况填写
String endpoint = "oss.cn-north-3.inspurcloudoss.com";
String accessKey = "<yourAccessKey>";
String secretKey = "<yourSecretKey>";
String bucketName = "<yourBucketName>";
String key = "<yourObjectName>";

//创建OSSClient实例
OSSClientImpl ossClient = new OSSClientImpl(endpoint, accessKey, secretKey);

//合并碎片
//第一个参数表示分片编号(partNumber),在分片的时候生成
//partETag表示分片的ETag号,可以在上传分片的返回值中得到
PartETag eTag = new PartETag(1, "<partETag>");
List<PartETag> eTags = new ArrayList<>();
eTags.add(eTag);
//objectUploadId表示文件的上传ID号,可以在初始化文件(ossClient.initiateMultipartUpload)的返回值得到
CompleteMultipartUploadRequest completeMultipartUploadRequest = new CompleteMultipartUploadRequest(bucketName, key, "<objectUploadId>", eTags);
CompleteMultipartUploadResult completeMultipartUploadResult = ossClient.completeMultipartUpload(completeMultipartUploadRequest);
System.out.println("Completing Multipart: " + completeMultipartUploadResult);

完整分片上传

以下代码用于分片上传:

// Endpoint以华北三为例,其它Region请按实际情况填写
String endpoint = "oss.cn-north-3.inspurcloudoss.com";
String accessKey = "<yourAccessKey>";
String secretKey = "<yourSecretKey>";
String bucketName = "<yourBucketName>";
String key = "<yourObjectName>";

//创建OSSClient实例
OSSClientImpl ossClient = new OSSClientImpl(endpoint, accessKey, secretKey);

//初始化文件,获取uploadId
InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(bucketName, key);
//初始化文件,必须设置文件上传后的访问权限
request.setAcl(CannedAccessControlList.PublicRead);
InitiateMultipartUploadResult initiateMultipartUploadResult = ossClient.initiateMultipartUpload(request);

//以本地文件test.exe为上传文件,并获取文件大小
File file = new File("D:\\test.exe");
long fileLength = file.length();

//以每片大小为5M为例
long perPartSize = 5 * 1024 * 1024;

//获取分片数量
long partCount = fileLength / perPartSize;
//如果分片的最后一片小于每片的大小,需要加上最后一片
if (fileLength % perPartSize != 0) {
    partCount++;
}
//如果文件大小为0需要设置分片数为1,否则会抛异常
if (fileLength == 0) {
    partCount = 1;
}

//partETags用来记录每一个分片上传后的partEtag(用来标识分片),用来最后进行分片合并
List<PartETag> partETags = new ArrayList<>();
for (int i = 0; i < partCount; i++) {
    long startPos = i * perPartSize;
    //判断是都是最后一片,如果是最后一片,大小是小于等于每一片大小的,需要设置大小为最后一片的大小
    long curPartSize = (i + 1 == partCount) ? (fileLength - startPos) : perPartSize;

    //跳过上一次已经上传的字节数,让上一次上传字节的后一个字节作为这一次上传的开始位置
    InputStream inputStream = new FileInputStream(file);
    inputStream.skip(startPos);

    UploadPartRequest uploadPartRequest = new UploadPartRequest(bucketName, key,             initiateMultipartUploadResult.getUploadId(), inputStream);
    uploadPartRequest.setPartSize(curPartSize);
    uploadPartRequest.setPartNumber( i + 1);

    //上传分片
    UploadPartResult uploadPartResult = ossClient.uploadPart(uploadPartRequest);

    //保存分片的partEtag
    partETags.add(new PartETag(uploadPartResult.getPartNumber(),                              uploadPartResult.geteTag()));
}

//进行文件的合并
CompleteMultipartUploadRequest completeMultipartUploadRequest = new CompleteMultipartUploadRequest(bucketName, key,
initiateMultipartUploadResult.getUploadId(),partETags);
ossClient.completeMultipartUpload(completeMultipartUploadRequest);

中止分片上传

以下代码用于中止上传:

// Endpoint以华北三为例,其它Region请按实际情况填写
String endpoint = "oss.cn-north-3.inspurcloudoss.com";
String accessKey = "<yourAccessKey>";
String secretKey = "<yourSecretKey>";
String bucketName = "<yourBucketName>";
String key = "<yourObjectName>";

//创建OSSClient实例
OSSClientImpl ossClient = new OSSClientImpl(endpoint, accessKey, secretKey);

//中止分片上传
//objectUploadId表示文件的上传ID号,可以在初始化文件(ossClient.initiateMultipartUpload)的返回值得到
AbortMultipartUploadRequest abortIncompleteMultipartUpload = new AbortMultipartUploadRequest(bucketName, key, "<objectUploadId>");
ossClient.abortMultipartUpload(abortIncompleteMultipartUpload);

列举分片上传事件

调用ossClient.getMultipartUploadList(ListMultipartUploadsRequest listMultipartUploadsRequest)方法列举出指定存储桶下所有已经上传成功的分片,参数ListMultipartUploadsRequest 主要包含以下属性:

属性 描述
String bucketName 存储桶的名字
String keyMarker 所有文件名称的字母序大于keyMarker参数值的分片上传事件。可以与uploadIdMarker参数一同使用来指定返回结果的起始位置。
String uploadIdMarker 与keyMarker参数一同使用来指定返回结果的起始位置。 如果未设置keyMarker参数,则此参数无效。如果设置了keyMarker参数,则查询结果中包含:名称的字母序大于keyMarker参数值的所有文件;文件名称等于keyMarker参数值且uploadId比uploadIdMarker参数值大的所有分片上传事件。
String prefix 限定返回的文件名称必须以指定的prefix作为前缀。注意使用prefix查询时,返回的文件名称中仍会包含prefix。
String delimiter 用于对文件名称进行分组的一个字符。所有名称包含指定的前缀且第一次出现delimiter字符之间的文件作为一组元素。
Integer maxUploads 限定此次返回分片上传事件的最大数目,默认值和最大值均为1000。
String encodingType 限定文件的编码格式,在其他基础上进一步限制返回结果
  • 列举全部分片上传事件

    默认情况下,listMultipartUploads 只能一次列举1000个分片。当分片数量大于1000时,可以采用以下代码列举全部分片上传事件。

// Endpoint以华北三为例,其它Region请按实际情况填写
String endpoint = "oss.cn-north-3.inspurcloudoss.com";
String accessKey = "<yourAccessKey>";
String secretKey = "<yourSecretKey>";
String bucketName = "<yourBucketName>";

//创建OSSClient实例
OSSClientImpl ossClient = new OSSClientImpl(endpoint, accessKey, secretKey);

// 列举分片上传事件。默认列举1000个分片
ListMultipartUploadsRequest listMultipartUploadsRequest = new ListMultipartUploadsRequest(bucketName);
MultipartUploadListing multipartUploadListing;
do {
    multipartUploadListing = ossClient.getMultipartUploadList(listMultipartUploadsRequest);

for (Upload upload : multipartUploadListing.getUploads()) {
    // 获取Key
    System.out.println(upload.getKey());
    // 获取uploadId
    System.out.println(upload.getUploadId());
    // 获取分片上传存储类型
    System.out.println(upload.getStorageClass());
    // 获取分片上传的用户信息
    System.out.println(upload.getOwner());
    // 获取分片上传的初始化时间
    System.out.println(upload.getInitiated());   
}

//设置下一次开始的位置为已经获取1000个后的下一个文件名称
listMultipartUploadsRequest.setKeyMarker(multipartUploadListing.getNextKeyMarker());
//设置下一次开始的uploadId位置  listMultipartUploadsRequest.setUploadIdMarker(multipartUploadListing.getNextUploadIdMarker());

} while (multipartUploadListing.isTruncated());
  • 分页列举全部上传事件

    以下代码用于分页列举所有上传事件:

// Endpoint以华北三为例,其它Region请按实际情况填写
String endpoint = "oss.cn-north-3.inspurcloudoss.com";
String accessKey = "<yourAccessKey>";
String secretKey = "<yourSecretKey>";
String bucketName = "<yourBucketName>";

//创建OSSClient实例
OSSClientImpl ossClient = new OSSClientImpl(endpoint, accessKey, secretKey);

//设置每一页需要列举的分片上传事件数目
ListMultipartUploadsRequest listMultipartUploadsRequest = new ListMultipartUploadsRequest(bucketName);
listMultipartUploadsRequest.setMaxUploads(20);

MultipartUploadListing multipartUploadListing;
do {
    multipartUploadListing = ossClient.getMultipartUploadList(listMultipartUploadsRequest);

for (Upload upload : multipartUploadListing.getUploads()) {
    // 获取Key
    System.out.println(upload.getKey());
    // 获取uploadId
    System.out.println(upload.getUploadId());
    // 获取分片上传存储类型
    System.out.println(upload.getStorageClass());
    // 获取分片上传的用户信息
    System.out.println(upload.getOwner());
    // 获取分片上传的初始化时间
    System.out.println(upload.getInitiated());   
}

//设置下一次开始的位置为已经获取20个后的下一个文件名称
listMultipartUploadsRequest.setKeyMarker(multipartUploadListing.getNextKeyMarker());
//设置下一次开始的uploadId位置  listMultipartUploadsRequest.setUploadIdMarker(multipartUploadListing.getNextUploadIdMarker());

} while (multipartUploadListing.isTruncated());