全部产品
存储与CDN 数据库 安全 应用服务 数加·人工智能 数加·大数据基础服务 互联网中间件 视频服务 开发者工具 解决方案 物联网
对象存储 OSS

分片上传

更新时间:2017-06-07 13:26:11

下面演示通过分片上传文件的整个流程:

初始化分片上传

  1. __block NSString * uploadId = nil;
  2. __block NSMutableArray * partInfos = [NSMutableArray new];
  3. NSString * uploadToBucket = @"<bucketName>";
  4. NSString * uploadObjectkey = @"<objectKey>";
  5. OSSInitMultipartUploadRequest * init = [OSSInitMultipartUploadRequest new];
  6. init.bucketName = uploadToBucket;
  7. init.objectKey = uploadObjectkey;
  8. // init.contentType = @"application/octet-stream";
  9. OSSTask * initTask = [client multipartUploadInit:init];
  10. [initTask waitUntilFinished];
  11. if (!initTask.error) {
  12. OSSInitMultipartUploadResult * result = initTask.result;
  13. uploadId = result.uploadId;
  14. } else {
  15. NSLog(@"multipart upload failed, error: %@", initTask.error);
  16. return;
  17. }
  • OSSInitMultipartUploadRequest指定上传文件的所属存储空间Bucket和文件名字。
  • multipartUploadInit发挥的结果中包含UploadId,是区分分片上传的唯一标示,后面的操作中会用到。

上传分片

  1. NSString * filePath = [docDir stringByAppendingPathComponent:@"***"];
  2. //要上传的文件
  3. int chuckCount = *;
  4. //分片上传数量
  5. uint64_t offset = fileSie/chuckCount;
  6. //分片大小
  7. for (int i = 1; i <= chuckCount; i++) {
  8. OSSUploadPartRequest * uploadPart = [OSSUploadPartRequest new];
  9. uploadPart.bucketName = uploadToBucket;
  10. uploadPart.objectkey = uploadObjectkey;
  11. uploadPart.uploadId = uploadId;
  12. uploadPart.partNumber = i; // part number start from 1
  13. NSFileHandle* readHandle = [NSFileHandle fileHandleForReadingAtPath:filePath];
  14. [readHandle seekToFileOffset:offset * (i -1)];
  15. NSData* data = [readHandle readDataOfLength:offset];
  16. uploadPart.uploadPartData = data;
  17. OSSTask * uploadPartTask = [client uploadPart:uploadPart];
  18. [uploadPartTask waitUntilFinished];
  19. if (!uploadPartTask.error) {
  20. OSSUploadPartResult * result = uploadPartTask.result;
  21. uint64_t fileSize = [[[NSFileManager defaultManager] attributesOfItemAtPath:uploadPart.uploadPartFileURL.absoluteString error:nil] fileSize];
  22. [partInfos addObject:[OSSPartInfo partInfoWithPartNum:i eTag:result.eTag size:fileSize]];
  23. } else {
  24. NSLog(@"upload part error: %@", uploadPartTask.error);
  25. return;
  26. }
  27. }

上述代码调用uploadPart来上传每一个分片,注意:

  • 每一个分片上传请求需指定UploadId和PartNum。
  • uploadPart要求除最后一个Part外,其他的Part大小都要大于100KB。但是Upload Part接口并不会立即校验上传。Part的大小(因为不知道是否为最后一块);只有当Complete Multipart Upload的时候才会校验。
  • Part号码的范围是1~10000。如果超出这个范围,OSS将返回InvalidArgument的错误码。
  • 每次上传part时都要把流定位到此次上传片开头所对应的位置。
  • 每次上传part之后,OSS的返回结果会包含一个分片的ETag,值为part数据的MD5值,您需要将它和块编号组合成PartEtag保存,后续完成分片上传需要用到。

完成分片上传

下面代码中的 partInfos就是进行分片上传中保存的partETag的列表,OSS收到用户提交的Part列表后,会逐一验证每个数据Part的有效性。当所有的数据Part验证通过后,OSS会将这些part组合成一个完整的文件。

  1. OSSCompleteMultipartUploadRequest * complete = [OSSCompleteMultipartUploadRequest new];
  2. complete.bucketName = uploadToBucket;
  3. complete.objectKey = uploadObjectkey;
  4. complete.uploadId = uploadId;
  5. complete.partInfos = partInfos;
  6. OSSTask * completeTask = [client completeMultipartUpload:complete];
  7. [[completeTask continueWithBlock:^id(OSSTask *task) {
  8. if (!task.error) {
  9. OSSCompleteMultipartUploadResult * result = task.result;
  10. // ...
  11. } else {
  12. // ...
  13. }
  14. return nil;
  15. }] waitUntilFinished];

完成分片上传(设置ServerCallback)

完成分片上传请求可以设置Server Callback参数,请求完成后会向指定的Server Adress发送回调请求;可通过查看返回结果的result.serverReturnJsonString,查看servercallback结果。

  1. OSSCompleteMultipartUploadRequest * complete = [OSSCompleteMultipartUploadRequest new];
  2. complete.bucketName = @"<bucketName>";
  3. complete.objectKey = @"<objectKey>";
  4. complete.uploadId = uploadId;
  5. complete.partInfos = partInfos;
  6. complete.callbackParam = @{
  7. @"callbackUrl": @"<server address>",
  8. @"callbackBody": @"<test>"
  9. };
  10. complete.callbackVar = @{
  11. @"var1": @"value1",
  12. @"var2": @"value2"
  13. };
  14. OSSTask * completeTask = [client completeMultipartUpload:complete];
  15. [[completeTask continueWithBlock:^id(OSSTask *task) {
  16. if (!task.error) {
  17. OSSCompleteMultipartUploadResult * result = task.result;
  18. NSLog(@"server call back return : %@", result.serverReturnJsonString);
  19. } else {
  20. // ...
  21. }
  22. return nil;
  23. }] waitUntilFinished];

删除分片上传事件

下面代码取消了对应UploadId的分片上传请求。

  1. OSSAbortMultipartUploadRequest * abort = [OSSAbortMultipartUploadRequest new];
  2. abort.bucketName = @"<bucketName>";
  3. abort.objectKey = @"<objectKey>";
  4. abort.uploadId = uploadId;
  5. OSSTask * abortTask = [client abortMultipartUpload:abort];
  6. [abortTask waitUntilFinished];
  7. if (!abortTask.error) {
  8. OSSAbortMultipartUploadResult * result = abortTask.result;
  9. uploadId = result.uploadId;
  10. } else {
  11. NSLog(@"multipart upload failed, error: %@", abortTask.error);
  12. return;
  13. }

罗列分片

调用listParts方法获取某个上传事件所有已上传的分片。

  1. OSSListPartsRequest * listParts = [OSSListPartsRequest new];
  2. listParts.bucketName = @"<bucketName>";
  3. listParts.objectKey = @"<objectkey>";
  4. listParts.uploadId = @"<uploadid>";
  5. OSSTask * listPartTask = [client listParts:listParts];
  6. [listPartTask continueWithBlock:^id(OSSTask *task) {
  7. if (!task.error) {
  8. NSLog(@"list part result success!");
  9. OSSListPartsResult * listPartResult = task.result;
  10. for (NSDictionary * partInfo in listPartResult.parts) {
  11. NSLog(@"each part: %@", partInfo);
  12. }
  13. } else {
  14. NSLog(@"list part result error: %@", task.error);
  15. }
  16. return nil;
  17. }];

注:默认情况下,如果存储空间中的分片上传事件的数量大于1000,则只会返回1000个Multipart Upload信息,且返回结果中 IsTruncated 为false,并返回 NextPartNumberMarker作为下此读取的起点。

本文导读目录