分片上传
本文介绍如何使用分片上传。
分片上传(Multipart Upload)分为以下三个步骤:
- 初始化一个分片上传事件。
调用oss.initMultipartUpload方法返回OSS创建的全局唯一的uploadId。
- 上传分片。
调用oss.uploadPart方法上传分片数据。
说明- 对于同一个uploadId,分片号(partNumber)标识了该分片在整个文件内的相对位置。如果使用同一个分片号上传了新的数据,那么OSS上这个分片已有的数据将会被覆盖。
- OSS将收到的分片数据的MD5值放在ETag头内返回给用户。
- OSS计算上传数据的MD5值,并与SDK计算的MD5值比较,如果不一致则返回InvalidDigest错误码。
- 完成分片上传。
所有分片上传完成后,调用oss.CompleteMultipartUpload方法将所有分片合并成完整的文件。
以下通过一个完整的示例对分片上传的流程进行逐步解析:
//初始化分片上传。
//InitiateMultipartUploadRequest用于指定上传文件的名称以及上传文件所属的存储空间的名称。
InitiateMultipartUploadRequest init = new InitiateMultipartUploadRequest("<bucketName>", "<objectKey>");
InitiateMultipartUploadResult initResult = oss.initMultipartUpload(init);
//initResult返回的结果中包含UploadId,UploadId用于唯一标识本次Multipart Upload事件。
String uploadId = initResult.getUploadId();
int partCount = 100*1024;
//分片上传
for (int i = 1;i<5;i++){
byte[] data = new byte[partCount];
RandomAccessFile raf = new RandomAccessFile("path", "r");
long skip = (i-1) * partCount;
raf.seek(skip);
raf.readFully(data, 0, partCount);
UploadPartRequest uploadPart = new UploadPartRequest();
uploadPart.setBucketName(mBucketName);
uploadPart.setObjectKey(objectKey);
uploadPart.setUploadId(uploadId);
uploadPart.setPartNumber(i); //上传的Part对应的part number从1开始标识。
uploadPart.setPartContent(data);
try {
oss.uploadPart(uploadPart);
} catch (ServiceException serviceException) {
OSSLog.logError(serviceException.getErrorCode());
}
}
//完成分片上传。
CompleteMultipartUploadRequest complete = new CompleteMultipartUploadRequest("<bucketName>", "<objectName>", "<uploadId>", "<partETagList>";
//上传回调。完成分片上传请求时可以设置CALLBACK_SERVER参数,请求完成后会向指定的Server Address发送回调请求。可通过返回结果的completeResult.getServerCallbackReturnBody()查看servercallback结果。
complete.setCallbackParam(new HashMap<String, String>() {
{
put("callbackUrl", CALLBACK_SERVER); //修改为您的服务器地址。
put("callbackBody", "test");
}
});
CompleteMultipartUploadResult completeResult = oss.completeMultipartUpload(complete);
OSSLog.logError("-------------- serverCallback: " + completeResult.getServerCallbackReturnBody());
上述代码调用 uploadPart 来上传每一个分片。
注意
- 每一个分片上传请求需指定 UploadId 和 PartNum 。
- uploadPart 要求除最后一个 Part 外,其他的 Part 大小都要大于100KB。但是 Upload Part 接口并不会立即校验上传。只有完成分片上传时才会校验 Part 的大小。
- Part 号码的范围是1~10000。如果超出这个范围,OSS 将返回 InvalidArgument 的错误码。
- 每次上传 Part 时都要把流定位到此次上传片开头所对应的位置。
- 每次上传 Part 之后,OSS 的返回结果会包含一个分片的 ETag值,ETag 值为 Part 数据的 MD5 值,您需要将 ETag 值和块编号组合成 PartEtag 并保存,用于后续完成分片上传。
列举已上传分片
调用 oss.listParts 方法获取某个上传事件所有已上传的分片。
以下代码用于列举已上传分片:
//列举分片。
ListPartsRequest listParts = new ListPartsRequest("<bucketName>", "<objectName>", "<uploadId>");
ListPartsResult result = oss.listParts(listParts);
List<PartETag> partETagList = new ArrayList<PartETag>();
for (PartSummary part : result.getParts()) {
partETagList.add(new PartETag(part.getPartNumber(), part.getETag()));
}
注意 默认情况下,如果存储空间中的分片上传事件的数量大于 1000,则只会返回 1000 个 Multipart Upload 信息,且返回结果中 IsTruncated
为 false,并返回 NextPartNumberMarker 作为下此读取的起点。
取消分片上传
调用 oss.abortMultipartUpload 方法取消对应 UploadId 的分片上传请求。当一个分片上传事件被取消后,无法再使用这个 uploadId 做任何操作,已经上传的分片数据会被删除。
以下代码用于取消分片上传:
//取消分片上传。
AbortMultipartUploadRequest abort = new AbortMultipartUploadRequest("<bucketName>", "<objectName>", "<uploadId>");
AbortMultipartUploadResult abortResult = oss.abortMultipartUpload(abort);
本地文件分片上传
通过获取文件路径进行本地文件分片上传有以下两种方法。
- 方法一
ObjectMetadata meta = new ObjectMetadata(); //设置文件元信息等。 meta.setHeader("x-oss-object-acl", "public-read-write"); MultipartUploadRequest rq = new MultipartUploadRequest("<bucketName>", "<objkey>", "<filepath>", meta); //设置PartSize。PartSize默认值为256KB,最小值为100KB。 rq.setPartSize(1024 * 1024); rq.setProgressCallback(new OSSProgressCallback<MultipartUploadRequest>() { @Override public void onProgress(MultipartUploadRequest request, long currentSize, long totalSize) { OSSLog.logDebug("[testMultipartUpload] - " + currentSize + " " + totalSize, false); } }); CompleteMultipartUploadResult result = oss.multipartUpload(rq);
- 方式二
MultipartUploadRequest request = new MultipartUploadRequest("<bucketName>", "<objkey>", "<filepath>"); request.setProgressCallback(new OSSProgressCallback<MultipartUploadRequest>() { @Override public void onProgress(MultipartUploadRequest request, long currentSize, long totalSize) { OSSLog.logDebug("[testMultipartUpload] - " + currentSize + " " + totalSize, false); } }); OSSAsyncTask task = oss.asyncMultipartUpload(request, new OSSCompletedCallback<MultipartUploadRequest, CompleteMultipartUploadResult>() { @Override public void onSuccess(MultipartUploadRequest request, CompleteMultipartUploadResult result) { OSSLog.logInfo(result.getServerCallbackReturnBody()); } @Override public void onFailure(MultipartUploadRequest request, ClientException clientException, ServiceException serviceException) { OSSLog.logError(serviceException.getRawMessage()); } }); // Thread.sleep(100); //取消分片上传。 // task.cancel(); task.waitUntilFinished();
版权声明
本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。
评论