最近更新时间:2025-04-25 15:43:03
public void listMultipartUploads() {
// 初始化 Ks3Client,参见“初始化”文档
Ks3Client ks3Client = initKs3Client();
try {
// 创建list请求,获取 example桶的分块列表
ListMultipartUploadsRequest request = new ListMultipartUploadsRequest("example");
/*
* keyMarker为空,uploadIdMarker不为空:无意义
*
* keyMarker不为空,uploadIdMarker不为空:
* 列出分块上传object key为keyMarker,且upload id 字典排序大于uploadIdMarker的结果
*
* keyMarker不为空,uploadIdMarker为空:
* 列出分块上传object key字典排序大于keyMarker的结果
*/
request.setKeyMarker("keyMarker");
request.setUploadIdMarker("uploadIdMarker");
/*
* prefix和delimiter详解
*
* commonPrefix由prefix和delimiter确定,以prefix开头的object key,
* 在prefix之后首次出现delimiter的位置之前(包含delimiter)的子字符串将存在于commonPrefixes中
* 比如有以下几个分块上传
*
* aaaa/bbb/ddd.txt
* aaaa/ccc/eee.txt
* ssss/eee/fff.txt
* prefix为空 delimiter为/
* 则commonPrefix 为 aaaa/和ssss/ 返回的uploads为空
*
* prefix为aaaa/ delimiter为/
* 则commonPrefix 为 aaaa/bbb/和aaaa/ccc/ 返回的uploads为空
*
* prefix为ssss/ delimiter为/
* 则commonPrefix 为 aaaa/eee/ 返回的uploads为空
*
* prefix为空 delimiter为空
* 则commonPrefix 为空 返回的uploads为aaaa/bbb/ddd.txt、aaaa/ccc/eee.txt、ssss/eee/fff.txt
*
* prefix为aaaa/ delimiter为空
* 则commonPrefix 为空 返回的uploads为aaaa/bbb/ddd.txt、aaaa/ccc/eee.txt
*
* prefix为ssss/ delimiter为空
* 则commonPrefix 为空 返回的uploads为ssss/eee/fff.txt
*/
request.setDelimiter("/");
request.setPrefix("prefix");
// 最多返回100条记录,默认(最多)是1000
request.setMaxUploads(100);
// 发起 list 请求
ListMultipartUploadsResult result = ks3Client.listMultipartUploads(request);
// 如果 isTruncated 为 true,说明结果被截断。
// 可以通过 nextKeyMarker 和 nextUploadIdMarker 作为下一次请求的 keyMarker 和 uploadIdMarker 继续请求
System.out.println("Is Truncated: " + result.isTruncated());
System.out.println("Next Key Marker: " + result.getNextKeyMarker());
System.out.println("Next Upload ID Marker: " + result.getNextUploadIdMarker());
System.out.println("Common Prefixes: " + result.getCommonPrefixes());
System.out.println("Uploads: " + result.getUploads());
} catch (Ks3ServiceException e) {
System.out.println("Ks3ServiceException occurred, which means the request was made to KS3, but KS3 returned an error response for some reason.");
System.out.println("Error Message: " + e.getErrorMessage());
System.out.println("Error Code: " + e.getErrorCode());
System.out.println("Request ID: " + e.getRequestId());
} catch (Ks3ClientException e) {
System.out.println("Ks3ClientException occurred, which means the client encountered an internal error while trying to communicate with KS3.");
System.out.println("Error Message: " + e.getMessage());
} finally {
// 不再使用时,关闭 Ks3Client
ks3Client.shutdown();
}
}
1. 最多只能返回1000条记录。
2. keyMarker、uploadIdMarker、delimiter、prefix、maxUploads都不是必要参数。用户可以根据自己的实际情况调节。
3. 当返回的result.isTruncated()为true时,需要用返回的result.getNextKeyMarker()和result.getNextUploadIdMarker参数作为keyMarker和uploadIdMarker继续罗列之后的分块上传。
public void listMultipartUploadsByIterator() {
// 初始化 Ks3Client,参见“初始化”文档
Ks3Client ks3Client = initKs3Client();
try {
// 创建list请求,获取 example桶的分块列表
ListMultipartUploadsRequest request = new ListMultipartUploadsRequest("example");
/*
* keyMarker为空,uploadIdMarker不为空:无意义
*
* keyMarker不为空,uploadIdMarker不为空:
* 列出分块上传object key为keyMarker,且upload id 字典排序大于uploadIdMarker的结果
*
* keyMarker不为空,uploadIdMarker为空:
* 列出分块上传object key字典排序大于keyMarker的结果
*/
request.setKeyMarker("keyMarker");
request.setUploadIdMarker("uploadIdMarker");
/*
* prefix和delimiter详解
*
* commonPrefix由prefix和delimiter确定,以prefix开头的object key,
* 在prefix之后首次出现delimiter的位置之前(包含delimiter)的子字符串将存在于commonPrefixes中
* 比如有以下几个分块上传
*
* aaaa/bbb/ddd.txt
* aaaa/ccc/eee.txt
* ssss/eee/fff.txt
* prefix为空 delimiter为/
* 则commonPrefix 为 aaaa/和ssss/ 返回的uploads为空
*
* prefix为aaaa/ delimiter为/
* 则commonPrefix 为 aaaa/bbb/和aaaa/ccc/ 返回的uploads为空
*
* prefix为ssss/ delimiter为/
* 则commonPrefix 为 aaaa/eee/ 返回的uploads为空
*
* prefix为空 delimiter为空
* 则commonPrefix 为空 返回的uploads为aaaa/bbb/ddd.txt、aaaa/ccc/eee.txt、ssss/eee/fff.txt
*
* prefix为aaaa/ delimiter为空
* 则commonPrefix 为空 返回的uploads为aaaa/bbb/ddd.txt、aaaa/ccc/eee.txt
*
* prefix为ssss/ delimiter为空
* 则commonPrefix 为空 返回的uploads为ssss/eee/fff.txt
*/
request.setDelimiter("/");
request.setPrefix("prefix");
// 最多返回100条记录,默认(最多)是1000
request.setMaxUploads(100);
// 使用迭代器列举分块上传
MultipartUploadListIterator iterator = ks3Client.newMultipartUploadListIterator(request);
while (iterator.hasNext()) {
ListMultipartUploadsResult result = iterator.next();
System.out.println("Common Prefixes: " + result.getCommonPrefixes());
System.out.println("Uploads: " + result.getUploads());
}
} catch (Ks3ServiceException e) {
System.out.println("Ks3ServiceException occurred, which means the request was made to KS3, but KS3 returned an error response for some reason.");
System.out.println("Error Message: " + e.getErrorMessage());
System.out.println("Error Code: " + e.getErrorCode());
System.out.println("Request ID: " + e.getRequestId());
} catch (Ks3ClientException e) {
System.out.println("Ks3ClientException occurred, which means the client encountered an internal error while trying to communicate with KS3.");
System.out.println("Error Message: " + e.getMessage());
} finally {
// 不再使用时,关闭 Ks3Client
ks3Client.shutdown();
}
}
public void initMultipartUpload() {
// 初始化 Ks3Client,参见“初始化”文档
Ks3Client ks3Client = initKs3Client();
try {
// 初始化分块上传
InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest("<your-bucket>", "<object-key>");
// 设置存储类型
request.setStorageClass(StorageClass.Standard);
// 设置ACL
request.setCannedAcl(CannedAccessControlList.Private);
// 或者设置自定义ACL
// AccessControlList accessControlList = new AccessControlList();
// accessControlList.addGrant(new GranteeId("id"), Permission.Read);
// request.setAcl(accessControlList);
// 设置元数据
ObjectMetadata objectMetadata = new ObjectMetadata();
objectMetadata.setContentType("text/plain");
objectMetadata.setUserMeta("user-meta-key", "user-meta-value");
request.setObjectMeta(objectMetadata);
// 设置标签
ObjectTagging objectTagging = new ObjectTagging();
objectTagging.addObjectTag("key1", "value1");
objectTagging.addObjectTag("key2", "value2");
request.setObjectTagging(objectTagging);
// 设置 KS3 托管密钥的服务端加密
objectMetadata.setSseAlgorithm("AES256");
// 或者设置客户提供密钥的服务端加密
// request.setSseCustomerKey(getCustomerKey());
// 设置是否禁止覆盖已有文件
request.setForbidOverwrite(true);
// 发起初始化分块上传请求
InitiateMultipartUploadResult initResult = ks3Client.initiateMultipartUpload(request);
String uploadId = initResult.getUploadId();
System.out.println("Upload ID: " + uploadId);
} catch (Ks3ServiceException e) {
System.out.println("Ks3ServiceException occurred, which means the request was made to KS3, but KS3 returned an error response for some reason.");
System.out.println("Error Message: " + e.getErrorMessage());
System.out.println("Error Code: " + e.getErrorCode());
System.out.println("Request ID: " + e.getRequestId());
} catch (Ks3ClientException e) {
System.out.println("Ks3ClientException occurred, which means the client encountered an internal error while trying to communicate with KS3.");
System.out.println("Error Message: " + e.getMessage());
} finally {
// 不再使用时,关闭 Ks3Client
ks3Client.shutdown();
}
}
1. 通过result.getUploadId()可以获取到本次上传的uploadId,之后的操作中将到会用到该uploadId。
2. 如果用户使用了客户提供秘钥的服务端加密算法(SSE-C),则下载文件的时候,必须提供加密秘钥,否则将无法下载。
提供文件、partSize和offset参数的方式上传。
public void uploadPart() {
// 初始化 Ks3Client,参见“初始化”文档
Ks3Client ks3Client = initKs3Client();
try {
UploadPartRequest request = new UploadPartRequest("<your-bucket>", "<object-key>");
// 设置分块上传 ID
request.setUploadId("<upload-id>");
// 设置分块号
request.setPartNumber(1);
// 设置分块大小,例:5MB
request.setPartSize(5 * 1024 * 1024);
// 设置文件及偏移量
request.setFile(new File("<path-of-your-file>"));
request.setFileoffset(0);
// 或者上传 InputStream
// byte[] data = "Hello, KS3!".getBytes();
// request.setInputStream(new ByteArrayInputStream(data));
// 使用 InputStream 时,分块大小需要设置为流的真实大小
// request.setPartSize(data.length);
PartETag partETag = ks3Client.uploadPart(request);
System.out.println("Part Number: " + partETag.getPartNumber());
System.out.println("Part Size: " + partETag.getPartSize());
System.out.println("Part ETag: " + partETag.geteTag());
System.out.println("Part CRC64: " + partETag.getCrc64Ecma());
} catch (Ks3ServiceException e) {
System.out.println("Ks3ServiceException occurred, which means the request was made to KS3, but KS3 returned an error response for some reason.");
System.out.println("Error Message: " + e.getErrorMessage());
System.out.println("Error Code: " + e.getErrorCode());
System.out.println("Request ID: " + e.getRequestId());
} catch (Ks3ClientException e) {
System.out.println("Ks3ClientException occurred, which means the client encountered an internal error while trying to communicate with KS3.");
System.out.println("Error Message: " + e.getMessage());
} finally {
// 不再使用时,关闭 Ks3Client
ks3Client.shutdown();
}
}
以下代码用于列举某个uploadId中已经上传的块:
public void listParts() {
// 初始化 Ks3Client,参见“初始化”文档
Ks3Client ks3Client = initKs3Client();
try {
// 创建 list 请求
ListPartsRequest request = new ListPartsRequest("<your-bucket>", "<object-key>", "<upload-id>");
// 设置最大返回的分块数,默认为 1000
request.setMaxParts(100);
// 设置分块号游标,将返回大于该分块号的分块
request.setPartNumberMarker(0);
// 发起 list 请求
ListPartsResult listPartsResult = ks3Client.listParts(request);
// 如果 isTruncated 为 true,说明结果被截断,可以通过 nextPartNumberMarker 作为下一次请求的 partNumberMarker 继续请求
System.out.println("Is Truncated: " + listPartsResult.isTruncated());
System.out.println("Next Part Number Marker: " + listPartsResult.getNextPartNumberMarker());
System.out.println("Parts: " + listPartsResult.getParts());
} catch (Ks3ServiceException e) {
System.out.println("Ks3ServiceException occurred, which means the request was made to KS3, but KS3 returned an error response for some reason.");
System.out.println("Error Message: " + e.getErrorMessage());
System.out.println("Error Code: " + e.getErrorCode());
System.out.println("Request ID: " + e.getRequestId());
} catch (Ks3ClientException e) {
System.out.println("Ks3ClientException occurred, which means the client encountered an internal error while trying to communicate with KS3.");
System.out.println("Error Message: " + e.getMessage());
} finally {
// 不再使用时,关闭 Ks3Client
ks3Client.shutdown();
}
}
参数说明:
参数 | 说明 |
---|---|
bucket | 初始化分块上传时的bucket |
key | 初始化分块上传时的key |
uploadId | 初始化分块上传获取到的uploadId |
该接口最多只会返回1000条记录,如果总数大于1000,请使用request.setPartNumberMarker()方法设置partNumber的起始位置。
public void listPartsByIterator() {
// 初始化 Ks3Client,参见“初始化”文档
Ks3Client ks3Client = initKs3Client();
try {
// 创建 list 请求
ListPartsRequest request = new ListPartsRequest("<your-bucket>", "<object-key>", "<upload-id>");
// 设置最大返回的分块数,默认为 1000
request.setMaxParts(100);
// 设置分块号游标,将返回大于该分块号的分块
request.setPartNumberMarker(0);
// 使用迭代器列举分块
PartListIterator iterator = ks3Client.newPartListIterator(request);
while (iterator.hasNext()) {
ListPartsResult listPartsResult = iterator.next();
System.out.println("Parts: " + listPartsResult.getParts());
}
} catch (Ks3ServiceException e) {
System.out.println("Ks3ServiceException occurred, which means the request was made to KS3, but KS3 returned an error response for some reason.");
System.out.println("Error Message: " + e.getErrorMessage());
System.out.println("Error Code: " + e.getErrorCode());
System.out.println("Request ID: " + e.getRequestId());
} catch (Ks3ClientException e) {
System.out.println("Ks3ClientException occurred, which means the client encountered an internal error while trying to communicate with KS3.");
System.out.println("Error Message: " + e.getMessage());
} finally {
// 不再使用时,关闭 Ks3Client
ks3Client.shutdown();
}
}
public void completeMultipartUpload() {
// 初始化 Ks3Client,参见“初始化”文档
Ks3Client ks3Client = initKs3Client();
try {
// 初始化分块 ETag 列表
List<PartETag> partETagList = new ArrayList<>();
//把上传块时返回的所有要合并的块依次添加进来
// partETagList.add(...)
// 初始化完成分块请求,设置 bucket,objectKey,uploadId,以及分块 ETag 列表
CompleteMultipartUploadRequest request = new CompleteMultipartUploadRequest("<your-bucket>", "<object-key>", "<upload-id>", partETagList);
// 设置禁止覆盖已有文件
request.setForbidOverwrite(true);
// 可以设置回调
// 如果用户设置了回调,那么当文件即将上传成功时,KS3将会使用POST的方式调用用户提供的回调地址,
// 如果调用成功且用户处理成功(用户处理成功指返回{"result":true}给KS3,处理失败返回{"result":false}),
// 那么文件才会真正的上传成功,如果调用失败或者用户处理失败,那么文件最终会上传失败。
// 用户可以设置KS3回调时的body,最后KS3将会把用户提供的参数组织成json格式返回给用户。
// 在下面示例中,KS3回调时的body为
// {
// "bucket":<实际存储的bucket>,
// "createTime":<文件创建时间>,
// "etag":<文件的etag,即文件的MD5经hex处理后的值>,
// "key":<文件实际保持的key>,
// "mimType":<文件的Content-Type>,
// "objectSize":<文件的字节数大小>,
// "time":"20150222"
// }
/*
* CallBackConfiguration config = new CallBackConfiguration();
* config.setCallBackUrl("http://10.4.2.38:19090/");//KS3服务器回调的地址
* // 以下为KS3服务器访问http://10.4.2.38:19090/时body中的参数
* Map<String,MagicVariables> magicVariables = new HashMap<String,MagicVariables>();
* magicVariables.put("bucket", MagicVariables.bucket);
* magicVariables.put("createTime", MagicVariables.createTime);
* magicVariables.put("etag", MagicVariables.etag);
* magicVariables.put("key", MagicVariables.key);
* magicVariables.put("mimeType", MagicVariables.mimeType);
* magicVariables.put("objectSize", MagicVariables.objectSize);
* config.setBodyMagicVariables(magicVariables);
* // 用户可以自己定义返回的参数。
* Map<String,String> kssVariables = new HashMap<String,String>();
* kssVariables.put("time", "20150222");
* request.setCallBackConfiguration(config);
*/
CompleteMultipartUploadResult result = ks3Client.completeMultipartUpload(request);
System.out.println("ETag: " + result.geteTag());
System.out.println("Crc64Ecma: " + result.getCrc64Ecma());
} catch (Ks3ServiceException e) {
System.out.println("Ks3ServiceException occurred, which means the request was made to KS3, but KS3 returned an error response for some reason.");
System.out.println("Error Message: " + e.getErrorMessage());
System.out.println("Error Code: " + e.getErrorCode());
System.out.println("Request ID: " + e.getRequestId());
} catch (Ks3ClientException e) {
System.out.println("Ks3ClientException occurred, which means the client encountered an internal error while trying to communicate with KS3.");
System.out.println("Error Message: " + e.getMessage());
} finally {
// 不再使用时,关闭 Ks3Client
ks3Client.shutdown();
}
}
对于不再使用的分块上传,建议调用该接口取消。
public void abortMultipartUpload() {
// 初始化 Ks3Client,参见“初始化”文档
Ks3Client ks3Client = initKs3Client();
try {
// 创建取消分块上传请求,设置 bucket,objectKey,uploadId
AbortMultipartUploadRequest request = new AbortMultipartUploadRequest("<your-bucket>", "<object-key>", "<upload-id>");
// 发起取消分块上传请求
ks3Client.abortMultipartUpload(request);
System.out.println("Abort multipart upload success.");
} catch (Ks3ServiceException e) {
System.out.println("Ks3ServiceException occurred, which means the request was made to KS3, but KS3 returned an error response for some reason.");
System.out.println("Error Message: " + e.getErrorMessage());
System.out.println("Error Code: " + e.getErrorCode());
System.out.println("Request ID: " + e.getRequestId());
} catch (Ks3ClientException e) {
System.out.println("Ks3ClientException occurred, which means the client encountered an internal error while trying to communicate with KS3.");
System.out.println("Error Message: " + e.getMessage());
} finally {
// 不再使用时,关闭 Ks3Client
ks3Client.shutdown();
}
}
以下通过一个完整的示例对分片上传的流程进行逐步解析:
public void multipartUpload() {
// 初始化 Ks3Client,参见“初始化”文档
Ks3Client ks3Client = initKs3Client();
try {
// 创建InitiateMultipartUploadRequest对象。
InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest("<your-bucket>", "<object-key>");
// 设置禁止覆盖已有文件
request.setForbidOverwrite(true);
// 如果需要在初始化分片时设置文件存储类型,请参考以下示例代码。更多设置参见“初始化分块上传”
// request.setStorageClass(StorageClass.StandardInfrequentAccess);
// 初始化分片。
InitiateMultipartUploadResult initResult = ks3Client.initiateMultipartUpload(request);
// 返回uploadId,它是分片上传事件的唯一标识。您可以根据该 uploadId 发起相关的操作,例如取消分片上传、查询分片上传等。
String uploadId = initResult.getUploadId();
// partETags是PartETag的集合。PartETag由分片的ETag和分片号组成。
List<PartETag> partETags = new ArrayList<>();
// 每个分片的大小,用于计算文件有多少个分片。单位为字节。
// 建议设置为5M(5*1024*1024)的整数倍,示例为 5MB。
final long partSize = 5 * 1024 * 1024L;
// 填写本地文件的完整路径。如果未指定本地路径,则默认从示例程序所属项目对应本地路径中上传文件。
final File sampleFile = new File("D:\\localpath\\examplefile.txt");
long fileLength = sampleFile.length();
int partCount = (int) (fileLength / partSize);
if (fileLength % partSize != 0) {
partCount++;
}
// 遍历分片上传。
for (int i = 0; i < partCount; i++) {
PartETag partETag = uploadPart(ks3Client, uploadId, sampleFile, i + 1, partSize);
partETags.add(partETag);
}
// 创建CompleteMultipartUploadRequest对象。
// 在执行完成分片上传操作时,需要提供所有有效的partETags。
// KS3收到提交的partETags后,会逐一验证每个分片的有效性。
// 当所有的数据分片验证通过后,KS3将把这些分片组合成一个完整的文件。
CompleteMultipartUploadRequest completeRequest = new CompleteMultipartUploadRequest("<your-bucket>", "<object-key>", uploadId, partETags);
// 设置禁止覆盖已有文件
completeRequest.setForbidOverwrite(true);
// 完成上传。
CompleteMultipartUploadResult completeMultipartUploadResult = ks3Client.completeMultipartUpload(completeRequest);
System.out.println("ETag: " + completeMultipartUploadResult.geteTag());
System.out.println("Crc64Ecma: " + completeMultipartUploadResult.getCrc64Ecma());
} catch (IOException e) {
System.out.println("IOException occurred, which means an I/O error occurred while trying to communicate with KS3.");
} catch (Ks3ServiceException e) {
System.out.println("Ks3ServiceException occurred, which means the request was made to KS3, but KS3 returned an error response for some reason.");
System.out.println("Error Message: " + e.getErrorMessage());
System.out.println("Error Code: " + e.getErrorCode());
System.out.println("Request ID: " + e.getRequestId());
} catch (Ks3ClientException e) {
System.out.println("Ks3ClientException occurred, which means the client encountered an internal error while trying to communicate with KS3.");
System.out.println("Error Message: " + e.getMessage());
} finally {
// 不再使用时,关闭 Ks3Client
ks3Client.shutdown();
}
}
private static PartETag uploadPart(Ks3Client ks3Client, String uploadId, File sampleFile, int partNum, long partSize) throws IOException {
long startPos = (partNum - 1) * partSize;
// 计算当前块的真实大小
long fileLength = sampleFile.length();
long curPartSize = Math.min(fileLength - startPos, partSize);
try (InputStream inputStream = Files.newInputStream(sampleFile.toPath())) {
// 跳过已经上传的分片。
inputStream.skip(startPos);
UploadPartRequest uploadPartRequest = new UploadPartRequest("<your-bucket>", "<object-key>");
uploadPartRequest.setUploadId(uploadId);
uploadPartRequest.setInputStream(inputStream);
// 设置分块大小。
// 除了最后一个块没有大小限制外,其余的块的大小均要求在100K以上。
// 如果不符合上述要求,会返回413状态码。
uploadPartRequest.setPartSize(curPartSize);
// 设置分片号。每一个上传的分片都有一个分片号,取值范围是1~10000.
uploadPartRequest.setPartNumber(partNum);
// 每次上传分片之后,KS3的返回结果包含PartETag。PartETag将被保存在partETags中。
return ks3Client.uploadPart(uploadPartRequest);
}
}
纯净模式