断点续传和分块上传

Posted BigBaHuang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了断点续传和分块上传相关的知识,希望对你有一定的参考价值。

#pragma mark   异步上传

- (void)uploadObjectAsync:(NSString *)FileURL objectKey:(NSString *)objectKey{

    OSSPutObjectRequest * put = [OSSPutObjectRequest new];

    NSLog(@"objectKey is %@",objectKey);

    // required fields

    put.bucketName = bucketName;

    put.objectKey = objectKey;

    put.uploadingFileURL = [NSURL fileURLWithPath:FileURL];

    

    // optional fields

    put.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) {

        

        NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);

        dispatch_async(dispatch_get_main_queue(), ^{

            float  gress = (double)totalByteSent/totalBytesExpectedToSend;

            if([self.dclickDelegate respondsToSelector:@selector(WaveProgressPlus:)]){

                [self.dclickDelegate performSelector:@selector(WaveProgressPlus:) withObject:@(gress)];

                NSLog(@"gress123上传中");

            }

        });

     

    };

    

    OSSTask * putTask = [client putObject:put];

    

    [putTask continueWithBlock:^id(OSSTask *task) {

        NSLog(@" putTask  :%@",putTask.result);

        NSLog(@"objectKey: %@", put.objectKey);

        uploadputkey = put.objectKey;

        if (!task.error) {

            NSLog(@"upload object success!");

            if([self.dclickDelegate respondsToSelector:@selector(dissbackView)]){

                [self.dclickDelegate performSelector:@selector(dissbackView)];

            }

            [self signAccessObjectURL];

        } else {

            NSLog(@"upload object failed, error: %@" , task.error);

        }

        return nil;

    }];

}

 

#pragma mark  同步上传

- (void)uploadObjectSync:(NSString *)FileURL objectKey:(NSString *)objectKey {

    OSSPutObjectRequest * put = [OSSPutObjectRequest new];

    

    // required fields

    put.bucketName = bucketName;

    put.objectKey = objectKey;

    put.uploadingFileURL = [NSURL fileURLWithPath:FileURL];

 

    // optional fields

    put.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) {

        NSLog(@"uploadProgress is  %lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);

        

        dispatch_async(dispatch_get_main_queue(), ^{

            float  gress = totalByteSent/totalBytesExpectedToSend;

            if([self.dclickDelegate respondsToSelector:@selector(WaveProgressPlus:)]){

                [self.dclickDelegate performSelector:@selector(WaveProgressPlus:) withObject:@(gress)];

                NSLog(@"gress123");

            }

        });

        

    };

 

    OSSTask * putTask = [client putObject:put];

    

    [putTask waitUntilFinished]; // 阻塞直到上传完成

    

    NSLog(@" putTask  :%@",putTask.result);

    if (!putTask.error) {

        NSLog(@"upload object success!");

        NSLog(@" putTask  :%@",putTask.result);

        NSLog(@"objectKey: %@", put.objectKey);

        uploadputkey = put.objectKey;

        if([self.dclickDelegate respondsToSelector:@selector(dissbackView)]){

            [self.dclickDelegate performSelector:@selector(dissbackView)];

        }

        [self signAccessObjectURL];

        

    } else {

        NSLog(@"upload object failed, error: %@" , putTask.error);

    }

    

}

 

#pragma mark  追加上传

 

- (void)appendObject {

    OSSAppendObjectRequest * append = [OSSAppendObjectRequest new];

    

    // 必填字段

    append.bucketName = @"android-test";

    append.objectKey = @"file1m";

    append.appendPosition = 0; // 指定从何处进行追加

    NSString * docDir = [self getDocumentDirectory];

    append.uploadingFileURL = [NSURL fileURLWithPath:[docDir stringByAppendingPathComponent:@"file1m"]];

    

    // 可选字段

    append.uploadProgress = ^(int64_t bytesSent, int64_t totalByteSent, int64_t totalBytesExpectedToSend) {

        NSLog(@"%lld, %lld, %lld", bytesSent, totalByteSent, totalBytesExpectedToSend);

    };

    // append.contentType = @"";

    // append.contentMd5 = @"";

    // append.contentEncoding = @"";

    // append.contentDisposition = @"";

    

    OSSTask * appendTask = [client appendObject:append];

     NSLog(@" putTask  :%@",appendTask.result);

    [appendTask continueWithBlock:^id(OSSTask *task) {

        NSLog(@"objectKey: %@", append.objectKey);

        if (!task.error) {

            NSLog(@"append object success!");

            OSSAppendObjectResult * result = task.result;

            NSString * etag = result.eTag;

            long nextPosition = result.xOssNextAppendPosition;

            NSLog(@"etag: %@, nextPosition: %ld", etag, nextPosition);

        } else {

            NSLog(@"append object failed, error: %@" , task.error);

        }

        return nil;

    }];

}

 

#pragma mark  异步下载

- (void)downloadObjectAsync {

    OSSGetObjectRequest * request = [OSSGetObjectRequest new];

    // required

    request.bucketName = @"android-test";

    request.objectKey = @"file1m";

    

    //optional

    request.downloadProgress = ^(int64_t bytesWritten, int64_t totalBytesWritten, int64_t totalBytesExpectedToWrite) {

        NSLog(@"%lld, %lld, %lld", bytesWritten, totalBytesWritten, totalBytesExpectedToWrite);

     

    };

   

    

    OSSTask * getTask = [client getObject:request];

    

    [getTask continueWithBlock:^id(OSSTask *task) {

        if (!task.error) {

            NSLog(@"download object success!");

            OSSGetObjectResult * getResult = task.result;

            NSLog(@"download dota length: %lu", [getResult.downloadedData length]);

            

        } else {

            NSLog(@"download object failed, error: %@" ,task.error);

        }

        return nil;

    }];

}

 

#pragma mark   同步下载

- (void)downloadObjectSync {

    OSSGetObjectRequest * request = [OSSGetObjectRequest new];

    // required

    request.bucketName = @"android-test";

    request.objectKey = @"file1m";

    

    //optional

    request.downloadProgress = ^(int64_t bytesWritten, int64_t totalBytesWritten, int64_t totalBytesExpectedToWrite) {

        NSLog(@"%lld, %lld, %lld", bytesWritten, totalBytesWritten, totalBytesExpectedToWrite);

    };

    // NSString * docDir = [self getDocumentDirectory];

    // request.downloadToFileURL = [NSURL fileURLWithPath:[docDir stringByAppendingPathComponent:@"downloadfile"]];

    

    OSSTask * getTask = [client getObject:request];

    

    [getTask waitUntilFinished];

    

    if (!getTask.error) {

        OSSGetObjectResult * result = getTask.result;

        NSLog(@"download data length: %lu", [result.downloadedData length]);

    } else {

        NSLog(@"download data error: %@", getTask.error);

    }

}

 

#pragma mark   获取meta

- (void)headObject {

    OSSHeadObjectRequest * head = [OSSHeadObjectRequest new];

    head.bucketName = @"android-test";

    head.objectKey = @"file1m";

    

    OSSTask * headTask = [client headObject:head];

    

    [headTask continueWithBlock:^id(OSSTask *task) {

        if (!task.error) {

            OSSHeadObjectResult * headResult = task.result;

            NSLog(@"all response header: %@", headResult.httpResponseHeaderFields);

            

            // some object properties include the ‘x-oss-meta-*‘s

            NSLog(@"head object result: %@", headResult.objectMeta);

        } else {

            NSLog(@"head object error: %@", task.error);

        }

        return nil;

    }];

}

 

#pragma mark   删除Object

- (void)deleteObject {

    OSSDeleteObjectRequest * delete = [OSSDeleteObjectRequest new];

    delete.bucketName = @"android-test";

    delete.objectKey = @"file1m";

    

    OSSTask * deleteTask = [client deleteObject:delete];

    

    [deleteTask continueWithBlock:^id(OSSTask *task) {

        if (!task.error) {

            NSLog(@"delete success !");

        } else {

            NSLog(@"delete erorr, error: %@", task.error);

        }

        return nil;

    }];

}

 

#pragma mark   复制Object

- (void)copyObjectAsync {

    OSSCopyObjectRequest * copy = [OSSCopyObjectRequest new];

    copy.bucketName = @"android-test"; // 复制到哪个bucket

    copy.objectKey = @"file_copy_to"; // 复制为哪个object

    copy.sourceCopyFrom = [NSString stringWithFormat:@"/%@/%@", @"android-test", @"file1m"]; // 从哪里复制

    

    OSSTask * copyTask = [client copyObject:copy];

    

    [copyTask continueWithBlock:^id(OSSTask *task) {

        if (!task.error) {

            NSLog(@"copy success!");

        } else {

            NSLog(@"copy error, error: %@", task.error);

        }

        return nil;

    }];

}

 

#pragma mark  签名URL授予第三方访问

- (void)signAccessObjectURL {

    NSString * constrainURL = nil;

    NSString * publicURL = nil;

    

    // sign constrain url

    OSSTask * task = [client presignConstrainURLWithBucketName:bucketName

                                                 withObjectKey:uploadputkey

                                        withExpirationInterval:60 * 30];

//    if (!task.error) {

//        constrainURL = task.result;

//        NSLog(@"constrainURL is %@",constrainURL);

//        postPublicURL = publicURL;

//        [self createTranscodeJobFlow];

//    } else {

//        NSLog(@"error: %@", task.error);

//    }

    

    // sign public url

    task = [client presignPublicURLWithBucketName:bucketName

                                    withObjectKey:uploadputkey];

    if (!task.error) {

        publicURL = task.result;

        NSLog(@"publicURL is %@",publicURL);

        postPublicURL = publicURL;

        [self createTranscodeJobFlow];

    } else {

        NSLog(@"sign url error: %@", task.error);

    }

}

 

#pragma mark   分块上传

- (void)multipartUpload:(NSString *)FileURL objectKey:(NSString *)objectKey{

    

    __block NSString * uploadId = nil;

    __block NSMutableArray * partInfos = [NSMutableArray new];

    

    NSString * uploadToBucket = bucketName;

    NSString * uploadObjectkey = objectKey;

    

    OSSInitMultipartUploadRequest * init = [OSSInitMultipartUploadRequest new];

    init.bucketName = uploadToBucket;

    init.objectKey = uploadObjectkey;

    init.contentType = @"video/x-m4v";

    init.objectMeta = [NSMutableDictionary dictionaryWithObjectsAndKeys:@"value1", @"x-oss-meta-name1", nil];

    

    OSSTask * initTask = [client multipartUploadInit:init];

    

    [initTask waitUntilFinished];

    

    if (!initTask.error) {

        OSSInitMultipartUploadResult * result = initTask.result;

        MUuploadID = result.uploadId;

        uploadputkey =objectKey;

       

        NSLog(@"init multipart upload success: %@", result.uploadId);

    } else {

        NSLog(@"multipart upload failed, error: %@", initTask.error);

        return;

    }

    NSDictionary * pathsize =  [self getVideoInfoWithSourcePath:FileURL];

    NSInteger videoSize = [pathsize[@"size"]integerValue];

    

    //要上传的文件

    chuckCount = 100; // 10块 好区分图谱

    //分片上传数量

    uint64_t offset = videoSize/chuckCount;

    

    for (int i = 1; i <= chuckCount; i++) {

        @autoreleasepool {

            OSSUploadPartRequest * uploadPart = [OSSUploadPartRequest new];

            uploadPart.bucketName = uploadToBucket;

            uploadPart.objectkey = uploadObjectkey;

            uploadPart.uploadId = uploadId;

            uploadPart.partNumber = i; // part number start from 1

            

            NSString * docDir = FileURL;

            uploadPart.uploadPartFileURL = [NSURL URLWithString:docDir];

            NSFileHandle* readHandle = [NSFileHandle fileHandleForReadingAtPath:FileURL];

            [readHandle seekToFileOffset:offset * (i -1)];

            NSData* data = [readHandle readDataOfLength:offset];

            uploadPart.uploadPartData = data;

            

 

//            uploadPart.uploadPartProgress = ^(int64_t bytesSent, int64_t totalBytesSent, int64_t totalBytesExpectedToSend) {

//                 NSLog(@"%lld %lld %lld", bytesSent, totalBytesSent, totalBytesExpectedToSend);

//                dispatch_async(dispatch_get_main_queue(), ^{

//                    float  gress = (double)totalBytesSent/totalBytesExpectedToSend;

//                    if([self.dclickDelegate respondsToSelector:@selector(WaveProgressPlus:)]){

//                        [self.dclickDelegate performSelector:@selector(WaveProgressPlus:) withObject:@(gress)];

//                        NSLog(@"gress123上传中");

//                    }

//                });

//            };

            

            OSSTask * uploadPartTask = [client uploadPart:uploadPart];

            

            [uploadPartTask waitUntilFinished];

            

            if (!uploadPartTask.error) {

                OSSUploadPartResult * result = uploadPartTask.result;

                uint64_t fileSize = [[[NSFileManager defaultManager] attributesOfItemAtPath:uploadPart.uploadPartFileURL.absoluteString error:nil] fileSize];

                [partInfos addObject:[OSSPartInfo partInfoWithPartNum:i eTag:result.eTag size:fileSize]];

                

                 [self listParts:MUuploadID PartNumber:uploadPart.partNumber];

            } else {

                NSLog(@"upload part error: %@", uploadPartTask.error);

                return;

            }

        }

    }

    

//    OSSCompleteMultipartUploadRequest * complete = [OSSCompleteMultipartUploadRequest new];

//    complete.bucketName = uploadToBucket;

//    complete.objectKey = uploadObjectkey;

//    complete.uploadId = uploadId;

//    complete.partInfos = partInfos;

//

//    OSSTask * completeTask = [client completeMultipartUpload:complete];

//

//    [completeTask waitUntilFinished];

//

//    if (!completeTask.error) {

//        NSLog(@"multipart upload success!");

//

//    } else {

//        NSLog(@"multipart upload failed, error: %@", completeTask.error);

//        return;

//    }

}

 

#pragma mark  罗列分块

- (void)listParts:(NSString *)uploadId PartNumber:(int)partNumber{

    OSSListPartsRequest * listParts = [OSSListPartsRequest new];

    listParts.bucketName = bucketName;

    listParts.objectKey = uploadputkey;

    listParts.uploadId = uploadId;

    

    OSSTask * listPartTask = [client listParts:listParts];

    

    [listPartTask continueWithBlock:^id(OSSTask *task) {

        if (!task.error) {

            NSLog(@"list part result success!");

            OSSListPartsResult * listPartResult = task.result;

            

            dispatch_async(dispatch_get_main_queue(), ^{

                float  gress = (double)partNumber/chuckCount;

                if([self.dclickDelegate respondsToSelector:@selector(WaveProgressPlus:)]){

                    [self.dclickDelegate performSelector:@selector(WaveProgressPlus:) withObject:@(gress)];

                    NSLog(@"gress123上传中");

                }

                if (gress == 1.0) {

              if([self.dclickDelegate respondsToSelector:@selector(dissbackView)]){

                        [self.dclickDelegate performSelector:@selector(dissbackView)];

              }

                    [self signAccessObjectURL];

                }

            });

            

            NSLog(@"listPartResult is%@",listPartResult);

            

            

            for (NSDictionary * partInfo in listPartResult.parts) {

                NSLog(@"partInfoeachpart: %@", partInfo);

            }

            

        } else {

            NSLog(@"list part result error: %@", task.error);

        }

        return nil;

    }];

}

#pragma mark ----// 断点续传 ----

 

- (void)resumableUpload:(NSString *)FileURL objectKey:(NSString *)objectKey{

    __block NSString * recordKey;

    

//    NSString * docDir = [self getDocumentDirectory];

    NSString * filePath =FileURL;

//    NSString * bucketName = bucketName;

//    objectKey = @"uploadKey";

    

    [[[[[[OSSTask taskWithResult:nil] continueWithBlock:^id(OSSTask *task) {

        // 为该文件构造一个唯一的记录键

        NSURL * fileURL = [NSURL fileURLWithPath:filePath];

        NSDate * lastModified;

        NSError * error;

        [fileURL getResourceValue:&lastModified forKey:NSURLContentModificationDateKey error:&error];

        if (error) {

            return [OSSTask taskWithError:error];

        }

        recordKey = [NSString stringWithFormat:@"%@-%@-%@-%@", bucketName, objectKey, [OSSUtil getRelativePath:filePath], lastModified];

        // 通过记录键查看本地是否保存有未完成的UploadId

        NSUserDefaults * userDefault = [NSUserDefaults standardUserDefaults];

        return [OSSTask taskWithResult:[userDefault objectForKey:recordKey]];

    }] continueWithSuccessBlock:^id(OSSTask *task) {

        if (!task.result) {

            // 如果本地尚无记录,调用初始化UploadId接口获取

            OSSInitMultipartUploadRequest * initMultipart = [OSSInitMultipartUploadRequest new];

            initMultipart.bucketName = bucketName;

            initMultipart.objectKey = objectKey;

            initMultipart.contentType = @"video/x-m4v";

            return [client multipartUploadInit:initMultipart];

        }

        OSSLogVerbose(@"An resumable task for uploadid: %@", task.result);

        return task;

    }] continueWithSuccessBlock:^id(OSSTask *task) {

        NSString * uploadId = nil;

        

        if (task.error) {

            return task;

        }

        

        if ([task.result isKindOfClass:[OSSInitMultipartUploadResult class]]) {

            uploadId = ((OSSInitMultipartUploadResult *)task.result).uploadId;

        } else {

            uploadId = task.result;

        }

        

        if (!uploadId) {

            return [OSSTask taskWithError:[NSError errorWithDomain:OSSClientErrorDomain

                                                              code:OSSClientErrorCodeNilUploadid

                                                          userInfo:@{OSSErrorMessageTOKEN: @"Can‘t get an upload id"}]];

        }

        // 将“记录键:UploadId”持久化到本地存储

        NSUserDefaults * userDefault = [NSUserDefaults standardUserDefaults];

        [userDefault setObject:uploadId forKey:recordKey];

        [userDefault synchronize];

        return [OSSTask taskWithResult:uploadId];

    }] continueWithSuccessBlock:^id(OSSTask *task) {

        // 持有UploadId上传文件

        _resumableUpload = [OSSResumableUploadRequest new];

        _resumableUpload.bucketName = bucketName;

        _resumableUpload.objectKey = objectKey;

        _resumableUpload.uploadId = task.result;

        _resumableUpload.uploadingFileURL = [NSURL fileURLWithPath:filePath];

        _resumableUpload.uploadProgress = ^(int64_t bytesSent, int64_t totalBytesSent, int64_t totalBytesExpectedToSend) {

            NSLog(@"%lld %lld %lld", bytesSent, totalBytesSent, totalBytesExpectedToSend);

            

                dispatch_async(dispatch_get_main_queue(), ^{

                    float  gress = (double)totalBytesSent/totalBytesExpectedToSend;

                    if([self.dclickDelegate respondsToSelector:@selector(WaveProgressPlus:)]){

                        [self.dclickDelegate performSelector:@selector(WaveProgressPlus:) withObject:@(gress)];

                        NSLog(@"gress123上传中");

                    }

                });

        };

        return [client resumableUpload:_resumableUpload];

    }] continueWithBlock:^id(OSSTask *task) {

        if (task.error) {

            if ([task.error.domain isEqualToString:OSSClientErrorDomain] && task.error.code == OSSClientErrorCodeCannotResumeUpload) {

                // 如果续传失败且无法恢复,需要删除本地记录的UploadId,然后重启任务

                [[NSUserDefaults standardUserDefaults] removeObjectForKey:recordKey];

            }

        } else {

           

            NSLog(@"%@",task.result);

            NSLog(@"%@",self->_resumableUpload.objectKey);

            NSLog(@"upload completed!");

             uploadputkey = _resumableUpload.objectKey;

            // 上传成功,删除本地保存的UploadId

            [[NSUserDefaults standardUserDefaults] removeObjectForKey:recordKey];

            NSLog(@"upload object success!");

            if([self.dclickDelegate respondsToSelector:@selector(dissbackView)]){

                [self.dclickDelegate performSelector:@selector(dissbackView)];

            }

            [self signAccessObjectURL];

        }

        return nil;

    }];

}

 

-(void)cannelUpdate{

    [_resumableUpload cancel];

//    _resumableUpload = nil;

    NSLog(@"取消网络操作");

//    [OSSTask cancelledTask];

}

 

#pragma mark --检查数据大小---

- (NSDictionary *)getVideoInfoWithSourcePath:(NSString *)path{

    NSLog(@"%@",path);

    

    AVURLAsset * asset = [AVURLAsset assetWithURL:[NSURL fileURLWithPath:path]];

    CMTime   time = [asset duration];

    int seconds = ceil(time.value/time.timescale);

    

    NSInteger   fileSize = [[NSFileManager defaultManager] attributesOfItemAtPath:path error:nil].fileSize;

    return @{@"size" : @(fileSize),

             @"duration" : @(seconds)};

}

以上是关于断点续传和分块上传的主要内容,如果未能解决你的问题,请参考以下文章

基于http的断点续传和多线程下载

java实现文件的断点续传和断点下载,有知道的交流下。

断点续传和下载原理分析

分块上传和断点续传

分块上传和断点续传

java web断点续传,我用的是fileupload来做的上传。