融合接口
功能说明
分片上传步骤较多,包括初始化、文件切片、各个分片上传、完成上传。为了简化分片上传,Java SDK 提供了分片上传的封装接口。您可以调用 TransferManager 接口,快速实现文件的分片上传与分片的管理。文件的上传时,TransferManager 会采用多线程的方式,同时进行多个文件的上传。
代码示例
使用 TransferManager 分片上传
public void upload() {
try {
String bucket = "<your-bucket-name>";
String key = "<your-object-key>";
String localPath = "<your-local-path>";
// TransferManager 只需要初始化一次,可以用于多个上传任务
TransferManager transMgr = TransferManagerBuilder.standard()
.withS3Client(s3Client)
// 设置最小分片大小,默认是5MB。
.withMinimumUploadPartSize(10*1024*1024L)
// 设置采用分片上传的阈值为100MB。只有当文件大于该值时,才会采用分片上传,否则采用普通上传。默认值是16MB。
.withMultipartUploadThreshold(100*1024*1024L)
.build();
// TransferManager 采用异步方式进行处理,因此该调用会立即返回。
PutObjectRequest request = new PutObjectRequest(bucket, key, new File(localPath));
request.withCannedAcl(CannedAccessControlList.Private); // 设置对象ACL,可以设置公共读CannedAccessControlList.PublicRead
// request.setStorageClass(StorageClass.Standard); // 设置对象的存储类别
ObjectMetadata meta = new ObjectMetadata();
meta.setContentType("application/octet-stream"); // 设置Content-Type,默认application/octet-stream
request.setMetadata(meta); // 还可以设置其他自定义元数据
Upload upload = transMgr.upload(request);
// 等待上传全部完成。
UploadResult result = upload.waitForUploadResult();
System.out.println("upload success, etag=" + result.getETag());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
使用 TransferManager 分片复制
public void copy() {
try {
String destBucketName = "<your-bucket-name>";
String destObjectKey = "<your-object-key>";
String sourceBucketName = "<source-bucket-name>";
String sourceObjectKey = "<source-object-key>";
// TransferManager 只需要初始化一次,可以用于多个上传任务
TransferManager transMgr = TransferManagerBuilder.standard()
.withS3Client(s3Client)
.withMinimumUploadPartSize(10*1024*1024L)
.withMultipartUploadThreshold(100*1024*1024L)
.build();
// TransferManager 采用异步方式进行处理,因此该调用会立即返回。
CopyObjectRequest request = new CopyObjectRequest(sourceBucketName, sourceObjectKey, destBucketName, destObjectKey);
Copy copy = transMgr.copy(request);
CopyResult result = copy.waitForCopyResult();
System.out.println("copy success, etag=" + result.getETag());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
取消分片上传
您可以使用 TransferManager.abortMultipartUploads 来取消分片上传。
public void abortMultipartUploads() {
String bucket = "<your-bucket-name>";
int sevenDays = 1000 * 60 * 60 * 24 * 7;
Date oneWeekAgo = new Date(System.currentTimeMillis() - sevenDays);
TransferManager transMgr = TransferManagerBuilder.standard()
.withS3Client(s3Client)
.build();
//取消在一个星期前初始化并还未完成的分片上传
transMgr.abortMultipartUploads(bucket, oneWeekAgo);
}
关于Content-Type的说明
Content-Type用于标识文件的资源类型,比如image/png
, image/jpg
是图片类型,video/mpeg
, video/mp4
是视频类型,text/plain
, text/html
是文本类型, 浏览器针对不同的Content-Type会有不同的操作,比如图片类型可以预览,视频类型可以播放,文本类型可以直接打开。application/octet-stream
类型会直接打开下载窗口。
在java sdk中,如果用户没有设置Content-Type,会根据PutObjectRequest中file参数的后缀扩展名自动生成Content-Type。
请求参数
参数 | 类型 | 说明 |
---|---|---|
localPath | String | 要上传的本地文件路径 |
bucket | String | 桶名 |
key | String | 对象key |
contentType | String | http contentType头 |
storageClass | StorageClass | 配置上传对象的存储类型,包括标准类型STANDARD、低频类型STANDARD_IA以及归档类型GLACIER |
metadata | ObjectMetadata | 对象自定义元数据 |
注意:acl在PutObjectRequest中设置
初始化分片上传任务
功能说明
分片上传操作可以将超过5GB的大文件分割后上传,分片上传对象首先需要发起分片上传请求获取一个upload id。
代码示例
System.out.println("multiPartUpload");
String bucket = "<your-bucket-name>";
String key = "<your-object-key>";
InitiateMultipartUploadRequest initReq = new InitiateMultipartUploadRequest(bucket, key);
initReq.withCannedACL(CannedAccessControlList.PublicRead);
// initReq.setStorageClass(StorageClass.Standard); // 设置对象的存储类型
InitiateMultipartUploadResult initRes = s3Client.initiateMultipartUpload(initReq);
System.out.println("multiPartUpload: init success, uploadId=" + initRes.getUploadId());
请求参数
InitiateMultipartUploadRequest 可设置的参数如下:
参数 | 类型 | 说明 | 是否必要 |
---|---|---|---|
bucket | String | 桶名称 | 是 |
key | String | 对象的key | 是 |
cannedAcl | CannedAccessControlList | 配置上传对象的预定义的标准ACL信息,详细说明见 设置对象访问权限 一节 | 否 |
storageClass | StorageClass | 配置上传对象的存储类型,包括标准类型STANDARD、低频类型STANDARD_IA以及归档类型GLACIER | 否 |
accessControlList | AccessControlList | 配置上传对象的详细ACL信息,详细说明见 设置对象访问权限 一节 | 是 |
objectMetadata | ObjectMetadata | 对象的元数据信息 | 否 |
tagging | ObjectTagging | 对象的标签信息 | 否 |
返回结果
InitiateMultipartUploadResult 返回的属性如下:
参数 | 类型 | 说明 |
---|---|---|
bucket | String | 执行分片上传的桶的名称 |
key | String | 本次分片上传对象的名称 |
uploadId | String | 本次生成分片上传任务的id |
上传分片
功能说明
初始化分片上传任务后,指定分片上传任务的id可以上传分片数据,可以将大文件分割成分片后上传,除了最后一个分片,每个分片的数据大小为5MB~5GB,每个分片上传任务最多上传10000个分片。
代码示例
String bucket = "<your-bucket-name>";
String key = "<your-object-key>";
String uploadId = "<your-upload-id>";
InputStream stream1 = new ByteArrayInputStream(new byte[5*1024*1024]);
UploadPartRequest partReq1 = new UploadPartRequest();
partReq1.setBucketName(bucket);
partReq1.setKey(key);
partReq1.setUploadId(uploadId); // 在 initiateMultipartUpload 获取
partReq1.setInputStream(stream1);
partReq1.setPartNumber(1); // 设置分片号代表这次复制是整个分片上传任务中的第几个分片,从1开始
partReq1.setObjectMetadata(new ObjectMetadata());
partReq1.setPartSize(stream1.available());
// rate 上传限速,单位KB
partReq1.putCustomRequestHeader("x-amz-limit", String.format("rate=%d", 10));
UploadPartResult partRes1 = s3Client.uploadPart(partReq1);
System.out.println("multiPartUpload: uploadPart success, etag=" + partRes1.getETag());
InputStream stream2 = new ByteArrayInputStream(new byte[1*1024*1024]);
UploadPartRequest partReq2 = new UploadPartRequest();
partReq2.setBucketName(bucket);
partReq2.setKey(key);
partReq2.setUploadId(uploadId);
partReq2.setInputStream(stream2);
partReq2.setPartNumber(2);
partReq2.setPartSize(stream2.available());
// rate 上传限速,单位KB
partReq2.putCustomRequestHeader("x-amz-limit", String.format("rate=%d", 10));
UploadPartResult partRes2 = s3Client.uploadPart(partReq2);
System.out.println("multiPartUpload: uploadPart success, etag=" + partRes2.getETag());
请求参数
UploadPartRequest 可设置的参数如下:
参数 | 类型 | 说明 | 是否必要 |
---|---|---|---|
bucket | String | 执行分片上传的桶的名称 | 是 |
key | String | 对象的key | 是 |
inputStream | InputStream | 对象的输入数据流 | 是 |
partNumber | int | 说明当前数据在文件中所属的分片,大于等于1,小于等于10000 | 是 |
uploadId | String | 通过 initiateMultipartUpload 操作获取的UploadId,与一个分片上传的对象对应 | 是 |
返回结果
UploadPartRequest 返回的属性如下:
参数 | 类型 | 说明 |
---|---|---|
etag | String | 本次上传分片对应的Entity Tag |
合并分片
功能说明
合并指定分片上传任务id对应任务中已上传的对象分片,使之成为一个完整的文件。
代码示例
String bucket = "<your-bucket-name>";
String key = "<your-object-key>";
String uploadId = "<your-upload-id>";
PartETag tag1 = new PartETag(partReq1.getPartNumber(), partRes1.getETag()); //partNumber与eTag在上传分片时获取
PartETag tag2 = new PartETag(partReq2.getPartNumber(), partRes2.getETag());
List<PartETag> partETags = new ArrayList<>();
partETags.add(tag1);
partETags.add(tag2);
CompleteMultipartUploadRequest completeReq = new CompleteMultipartUploadRequest(bucket, key, uploadId, partETags);
CompleteMultipartUploadResult completeRes = s3Client.completeMultipartUpload(completeReq);
System.out.println("multiPartUpload: complete success, etag=" + completeRes.getETag());
System.out.println("bucket=" + completeRes.getBucketName());
System.out.println("key=" + completeRes.getKey());
System.out.println("location=" + completeRes.getLocation());
System.out.println("versionId=" + completeRes.getVersionId());
请求参数
CompleteMultipartUploadRequest 可设置的参数如下:
参数 | 类型 | 说明 | 是否必要 |
---|---|---|---|
bucket | String | 执行分片上传的桶的名称 | 是 |
key | String | 对象的key | 是 |
partETags | List<PartETag> | 包含了每个已上传的分片的ETag和PartNumber等信息 | 是 |
uploadId | String | 通过CreateMultipartUpload操作获取的UploadId,与一个对象的分片上传对应 | 是 |
返回结果
CompleteMultipartUploadResult 返回的属性如下:
参数 | 类型 | 说明 |
---|---|---|
bucketName | String | 执行分片上传的桶的名称 |
key | String | 对象的key |
etag | String | 本次上传对象后对应的Entity Tag |
location | String | 合并生成对象的URI信息 |
versionId | String | 上传对象后相应的版本ID |
列举分片上传任务
功能说明
列举分片上传操作可以列出一个桶中正在进行的分片上传,这些分片上传的请求已经发起,但是还没完成或者被中止。listMultipartUploads 操作可以通过指定maxUploads参数来设置返回分片上传信息的数量,maxUploads参数的最大值和默认值均为1000。如果返回结果中的isTruncated字段为true,表示还有符合条件的分片上传信息没有列出,可以通过设置请求中的keyMarker和uploadIdMarker参数,来列出符合筛选条件的正在上传的分片信息。
代码示例
public void listMultipartUploads(){
String bucket = "<your-bucket-name>";
ListMultipartUploadsRequest listMultipartUploadsRequest = new ListMultipartUploadsRequest(bucket);
MultipartUploadListing multipartUploadListing = s3Client.listMultipartUploads(listMultipartUploadsRequest);
for (MultipartUpload multipartUpload : multipartUploadListing.getMultipartUploads()) {
System.out.println("uploadId=" + multipartUpload.getUploadId());
System.out.println("initiator=" + multipartUpload.getInitiator());
System.out.println("initiated=" + multipartUpload.getInitiated());
System.out.println("key=" + multipartUpload.getKey());
}
}
如果list大于1000,则返回的结果中 isTruncated 为true,并返回 NextKeyMarker NextUploadIdMarker 作为下次读取的起点。如果没有一次性获取所有的分片上传事件,可以采用分页列举的方式。列举所有分片上传事件示例代码如下:
public void listMultipartUploads2(){
String bucket = "<your-bucket-name>";
MultipartUploadListing multipartUploadListing;
ListMultipartUploadsRequest listMultipartUploadsRequest = new
ListMultipartUploadsRequest(bucket);
do {
multipartUploadListing = s3Client.listMultipartUploads(listMultipartUploadsRequest);
for (MultipartUpload multipartUpload : multipartUploadListing.getMultipartUploads()) {
System.out.println("uploadId=" + multipartUpload.getUploadId());
System.out.println("initiator=" + multipartUpload.getInitiator());
System.out.println("initiated=" + multipartUpload.getInitiated());
System.out.println("key=" + multipartUpload.getKey());
}
listMultipartUploadsRequest.setKeyMarker(multipartUploadListing.getNextKeyMarker());
listMultipartUploadsRequest.setUploadIdMarker(multipartUploadListing.getNextUploadIdMarker());
} while (multipartUploadListing.isTruncated());
}
请求参数
ListMultipartUploadsRequest 可设置的参数如下:
参数 | 类型 | 说明 | 是否必要 |
---|---|---|---|
bucket | String | 执行本操作的桶名称 | 是 |
delimiter | String | 与Prefix参数一起用于对对象key进行分组的字符。所有key包含指定的Prefix且第一次出现Delimiter字符之间的对象作为一组。如果没有指定Prefix参数,按Delimiter对所有对象key进行分割,多个对象分割后从对象key开始到第一个Delimiter之间相同的部分形成一组 | 否 |
encodingType | String | 用于设置response中object key的字符编码类型 | 否 |
keyMarker | String | 和uploadIdMarker参数一起用于指定返回哪部分分片上传的信息。如果没有设置uploadIdMarker参数,则只返回对象key按照字典顺序排序后位于keyMarker标识符之后的分片信息。如果设置了uploadIdMarker参数,则会返回对象key等于keyMarker且uploadId大于uploadIdMarker的分片信息 | 否 |
maxUploads | int | 用于指定相应消息体中正在进行的分片上传信息的最大数量,最小值为1,默认值和最大值都是1000 | 否 |
prefix | String | 与delimiter参数一起用于对对象key进行分组的字符。所有key包含指定的Prefix且第一次出现delimiter字符之间的对象作为一组 | 否 |
uploadIdMarker | String | 和keyMarker参数一起用于指定返回哪部分分片上传的信息,仅当设置了keyMarker参数的时候有效。设置后返回对象key等于keyMarker且uploadId大于uploadIdMarker的分片信息 | 否 |
返回结果
MultipartUploadListing 返回的属性如下:
参数 | 类型 | 说明 |
---|---|---|
bucketName | String | 执行本操作的桶名称 |
commonPrefixes | List<String> | 当请求中设置了delimiter和prefix属性时,所有包含指定的prefix且第一次出现delimiter字符的对象key作为一组 |
delimiter | String | 与请求中设置的delimiter一致 |
isTruncated | boolean | 当为false时表示返回结果中包含了全部符合本次请求查询条件的上传分片信息,否则只返回了数量为maxUploads个的分片信息 |
keyMarker | String | 返回上传分片列表中的起始对象的key |
maxUploads | int | 本次返回结果中包含的上传分片数量的最大值 |
nextKeyMarker | String | 当isTruncated为true时,nextKeyMarker可以作为后续查询已初始化的上传分片请求中的keyMarker的值 |
nextUploadIdMarker | String | 当isTruncated为true时,nextKeyMarker可以作为后续查询已初始化的上传分片请求中的uploadIdMarker的值 |
prefix | String | 限定返回分片中对应对象的key必须以prefix作为前缀 |
uploadIdMarker | String | 返回上传分片列表中的起始uploadId |
uploads | List<MultipartUpload> | 包含了零个或多个已初始化的上传分片信息的数组。数组中的每一项包含了分片初始化时间、分片上传操作发起者、对象key、对象拥有者、存储类型和uploadId等息 |
列举已上传的分片
功能说明
列举已上传分片操作可以列出一个分片上传操作中已经上传完毕但是还未合并的分片信息。请求中需要提供object key和 upload id,返回的结果最多包含1000个已上传的分片信息,默认返回1000个,可以通过设置maxParts参数的值指定返回结果中分片信息的数量。如果已上传的分片信息的数量多于1000个,则返回结果中的isTruncated字段为true,可用通过设置partNumberMarker参数获取partNumber大于该参数的分片信息。
代码示例
public void listParts() {
System.out.println("ListParts");
String bucket = "<your-bucket-name>";
String key = "<your-object-key>";
String uploadId = "<your-upload-id>";
ListPartsRequest listParts = new ListPartsRequest(bucket, key, uploadId);
PartListing partListing = this.s3Client.listParts(listParts);
System.out.println("bukcet=" + partListing.getBucketName() + ", key=" + partListing.getKey() + ", uploadId="+partListing.getUploadId());
for (PartSummary part : partListing.getParts()) {
System.out.println("part number="+part.getPartNumber()+", size="+part.getSize());
}
}
如果分片数大于1000,返回的 PartListing 中 isTruncated 为 true ,并可以根据 NextPartNumberMarker 为下一次请求的 list 的起始位置。
public void listParts2() {
System.out.println("ListParts");
String bucket = "<your-bucket-name>";
String key = "<your-object-key>";
String uploadId = "<your-upload-id>";
ListPartsRequest listParts = new ListPartsRequest(bucket, key, uploadId);
PartListing partListing;
ListPartsRequest listPartsRequest = new ListPartsRequest(bucket, key, uploadId);
do {
partListing = s3Client.listParts(listPartsRequest);
System.out.println("bukcet=" + partListing.getBucketName() + ", key=" + partListing.getKey() + ", uploadId="+partListing.getUploadId());
for (PartSummary part : partListing.getParts()) {
System.out.println("part number="+part.getPartNumber()+", size="+part.getSize());
}
listPartsRequest.setPartNumberMarker(partListing.getNextPartNumberMarker());
} while (partListing.isTruncated());
}
请求参数
ListPartsRequest 可设置的参数如下:
参数 | 类型 | 说明 | 是否必要 |
---|---|---|---|
bucket | String | 执行本操作的桶名称 | 是 |
key | String | 对象的key | 是 |
maxParts | int | 指定返回分片信息的数量,默认值和最大值均为1000 | 否 |
partNumberMarker | int | 用于指定返回part number大于partNumberMarker的分片信息 | 否 |
uploadId | String | 指定返回该id所属的分片上传的分片信息 | 是 |
返回结果
PartListing 返回的属性如下:
参数 | 类型 | 说明 |
---|---|---|
bucketName | String | 执行本操作的桶名称 |
key | String | 本次分片上传对象的名称 |
isTruncated | boolean | 当为false时表示返回结果中包含了全部符合本次请求查询条件的上传分片信息,否则只返回了数量为MaxParts个的分片信息 |
maxParts | int | 本次返回结果中包含的上传分片数量的最大值 |
nextPartNumberMarker | int | 当IsTruncated为true时,NextPartNumberMarker可以作为后续查询已上传分片请求中的PartNumberMarker的值 |
parts | List<PartSummary> | 包含了已上传分片信息的数组,数组中的每一项包含了该分片的Entity tag、最后修改时间、PartNumber和大小等信息 |
uploadId | String | 本次分片上传操作Id |
复制分片
功能说明
复制分片操作可以从一个已存在的对象中复制指定分片的数据。您可以使用 copyPart 复制分片。在复制分片前,需要使用 initiateMultipartUpload 接口获取一个upload id,在完成复制和上传分片操作之后,需要使用 completeMultipartUpload 操作组装分片成为一个对象。当复制的对象大小超过5GB,必须使用复制分片操作完成对象的复制。除了最后一个分片外,每个复制分片的大小范围是[5MB,5GB]。
代码示例
String destBucketName = "<your-bucket-name>";
String destObjectKey = "<your-object-key>";
String sourceBucketName = "<source-bucket-name>";
String sourceObjectKey = "<source-object-key>";
List<PartEtag> partEtags = new ArrayList<PartEtag>();
// 创建分片复制请求
CopyPartRequest copyRequest = new CopyPartRequest()
//设置源桶和对象,目标桶和对象
.withSourceBucketName(sourceBucketName)
.withSourceKey(sourceObjectKey)
.withDestinationBucketName(destBucketName)
.withDestinationKey(destObjectKey)
//uploadId为initiateMultipartUpload中返回值
.withUploadId(initResult.getUploadId())
//设置分片复制范围
.withFirstByte(firstByte)
.withLastByte(lastByte)
//设置分片号,代表这次复制是整个分片上传任务中的第几个分片
.withPartNumber(partNum);
CopyPartResult copyPartResult = s3.copyPart(copyRequest);
partETags.add(copyPartResult.getPartETag()); //把 partETag 放入 PartEtag 列表中,合并分片是需要此参数
System.out.println("multiPartCopy: copyPart success, part " + partNum + ", etag=" + copyPartResult.getETag());
System.out.println("lastModifiedDate=" + copyPartResult.getLastModifiedDate());
System.out.println("partNumber=" + copyPartResult.getPartNumber());
请求参数
copyRequest 可设置的参数如下:
参数 | 类型 | 说明 | 是否必要 |
---|---|---|---|
sourceBucketName | String | 源桶名称 | 是 |
sourceKey | String | 源对象key | 是 |
destinationBucketName | String | 目标桶名称 | 是 |
destinationKey | String | 目标对象key | 是 |
matchingETagConstraints | List<String> | 用于指定只有在源对象的eTag和该参数值匹配的情况下才进行复制操作。 | 否 |
modifiedSinceConstraint | Date | 用于只有当源对象在指定时间后被修改的情况下才进行复制操作 | 否 |
nonmatchingEtagConstraints | List<String> | 用于指定只有在源对象的eTag和该参数值不匹配的情况下才进行复制操作。 | 否 |
unmodifiedSinceConstraint | Date | 用于仅当源自指定时间以来未被修改的情况下才进行复制操作 | 否 |
firstByte | long | 指定本次分片复制的数据范围,源对象的起始字节 | 是 |
lastByte | long | 指定本次分片复制的数据范围,源对象的结束字节 | 是 |
partNumber | int | 说明本次分片复制的数据在原对象中所属的部分 | 是 |
uploadId | String | 与本次复制操作相应的分片上传Id | 是 |
返回结果
CopyPartResult 返回的属性如下:
参数 | 类型 | 说明 |
---|---|---|
etag | String | 包含复制分片的Entity Tag |
lastModifiedDate | Date | 复制分片的最新修改时间 |
partNumber | String | 分片序号 |
取消分片上传任务
功能说明
取消分片上传任务操作用于终止一个分片上传。当一个分片上传被中止后,不会再有数据通过与之相应的upload id上传,同时已经被上传的分片所占用的空间会被释放。执行取消分片上传任务操作后,正在上传的分片可能会上传成功也可能会被中止,所以必要的情况下需要执行多次取消分片上传任务操作去释放全部上传成功的分片所占用的空间。可以通过执行列举已上传分片操作来确认所有中止分片上传后所有已上传分片的空间是否被被释放。
代码示例
String bucket = "<your-bucket-name>";
String key = "<your-object-key>";
String uploadId = "<your-upload-id>";
System.out.println("multiPartUpload: error=" + e.getMessage());
AbortMultipartUploadRequest abortReq = new AbortMultipartUploadRequest(bucket, key, uploadId);
s3Client.abortMultipartUpload(abortReq);
请求参数
AbortMultipartUploadRequest 可设置的参数如下:
参数 | 类型 | 说明 | 是否必要 |
---|---|---|---|
bucket | String | 执行本操作的桶名称 | 是 |
key | String | 分片上传的对象的key | 是 |
uploadId | String | 指定需要终止的分片上传的id | 是 |