开发者社区> 问答> 正文

iOS-SDK之如何实现分片上传(一)?

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

初始化分片上传

  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];






展开
收起
青衫无名 2017-10-18 14:39:43 2465 0
0 条回答
写回答
取消 提交回答
问答排行榜
最热
最新

相关电子书

更多
手淘iOS性能优化探索 立即下载
From Java/Android to Swift iOS 立即下载
深入剖析iOS性能优化 立即下载