123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450 |
- //
- // CWUploadTask.m
- // uploadFileDemo
- //
- // Created by hyjet on 2018/3/9.
- // Copyright © 2018年 uploadFileDemo. All rights reserved.
- //
- #import "CWUploadTask.h"
- #import "CWFileUploadManager.h"
- #import "CWFileStreamSeparation.h"
- #import "CWFileManager.h"
- #import "CWUploadTask+CheckInfo.h"
- //分隔符
- #define Boundary @"1a2b3c"
- //一般换行
- #define Wrap1 @"\r\n"
- //key-value换行
- #define Wrap2 @"\r\n\r\n"
- //开始分割
- #define StartBoundary [NSString stringWithFormat:@"--%@%@",Boundary,Wrap1]
- //文件分割完成
- #define EndBody [NSString stringWithFormat:@"--%@--",Boundary]
- //一个片段上传失败默认重试3次
- #define REPEAT_MAX 3
- //#define plistPath [[CWFileManager cachesDir] stringByAppendingPathComponent:uploadPlist]
- #define GETPOSTFLOWCHUNKAPI @"/nextcloud/index.php/apps/rcapi/ajax/upload.php"/*断点续传*/
- NSString *const CWUploadTaskExeing = @"TaskExeing";
- NSString *const CWUploadTaskExeError = @"TaskExeError";
- NSString *const CWUploadTaskExeEnd = @"TaskExeEnd";
- NSString *const CWUploadTaskExeSuspend = @"TaskExeSuspend";
- @interface CWUploadTask ()
- //@property (nonatomic,strong)NSURLSessionUploadTask *uploadTask;
- //@property (nonatomic,strong)NSMutableURLRequest *request;
- //@property (nonatomic,readwrite)NSURLSessionTaskState taskState;
- @property (nonatomic,readwrite)NSURL * url;
- @property (nonatomic,readwrite)NSString *ID;
- @property (nonatomic,readwrite)NSMutableDictionary *param;//上传时参数
- @property (nonatomic,readwrite)CWFileStreamSeparation *fileStream;
- @property (nonatomic,copy)finishHandler finishBlock;//片段上传成功上传的回调block
- @property (nonatomic,copy)success successBlock;//整体上传成功上传的回调block
- @property (nonatomic,copy)NSString *chunkNumName;//片段编号这一参数的参数名
- @property (nonatomic,copy)NSDictionary *lastParam;//片段完成上传后的参数
- @property (nonatomic,assign)NSInteger chunkNo;//片段完成上传后的编号
- @property (nonatomic,assign)NSInteger taskRepeatNum;//重试次数
- @property (nonatomic,assign)BOOL isSuspendedState;//记录状态更改
- @property (nonatomic,strong)CWFileUploadManager *uploadManager;
- @end
- @implementation CWUploadTask
- -(CWFileUploadManager *)uploadManager
- {
- if (!_uploadManager) {
- _uploadManager = [CWFileUploadManager shardUploadManager];
- }
- return _uploadManager;
- }
- - (void)setFileStream:(CWFileStreamSeparation *)fileStream
- {
- _fileStream.fileStatus = CWUploadStatusWaiting;
- _taskRepeatNum = 0;
- _ID = fileStream.md5String;
- for (NSInteger idx=0; idx<fileStream.streamFragments.count; idx++) {
- CWStreamFragment *fragment = fileStream.streamFragments[idx];
- if (!fragment.fragmentStatus) {
- _chunkNo = idx;
- }
- }
- _fileStream = fileStream;
- }
- + (NSMutableDictionary<NSString*,CWUploadTask*> *)uploadTasksWithDict:(NSDictionary<NSString*,CWFileStreamSeparation*> *)dict{
- NSMutableDictionary *taskDict = [NSMutableDictionary dictionary];
- for (NSString *key in dict.allKeys) {
- CWFileStreamSeparation *fs = [dict objectForKey:key];
- CWUploadTask *task = [CWUploadTask initWithStreamModel:fs];
- [taskDict setValue:task forKey:key];
- }
- return taskDict;
- }
- + (instancetype)initWithStreamModel:(CWFileStreamSeparation *)fileStream
- {
- CWUploadTask *task = [CWUploadTask new];
- task.fileStream = fileStream;
- task.timeStamp = [iTools getNowTimeStamp];
- task.isSuspendedState = NO;
- task.url = [CWFileUploadManager shardUploadManager].url;
- return task;
- }
- - (void)listenTaskExeCallback:(finishHandler _Nonnull)block success:(success)successBlock
- {
- self.finishBlock = block;
- self.successBlock = successBlock;
- if (_finishBlock) _finishBlock(_fileStream,nil);
- }
- - (instancetype _Nonnull)initWithStreamModel:(CWFileStreamSeparation *)fileStream finish:(finishHandler _Nonnull)block success:(success)successBlock
- {
- if (self = [super init]) {
- self.fileStream = fileStream;
- _finishBlock = block;
- _successBlock = successBlock;
- }
- return self;
- }
- //-(NSMutableURLRequest*)uploadRequest
- //{
- // if ([CWFileUploadManager shardUploadManager].request) {
- // _request = [CWFileUploadManager shardUploadManager].request;
- // }else{
- // HLog(@"请配置上传任务的request");
- // }
- // return _request;
- //
- //}
- -(NSData*)taskRequestBodyWithParam:(NSDictionary *)param uploadData:(NSData *)data
- {
- NSMutableData* totlData=[NSMutableData new];
- NSArray* allKeys=[param allKeys];
- for (int i=0; i<allKeys.count; i++)
- {
-
- NSString *disposition = [NSString stringWithFormat:@"%@Content-Disposition: form-data; name=\"%@\"%@",StartBoundary,allKeys[i],Wrap2];
- NSString* object=[param objectForKey:allKeys[i]];
- disposition =[disposition stringByAppendingString:[NSString stringWithFormat:@"%@",object]];
- disposition =[disposition stringByAppendingString:Wrap1];
- [totlData appendData:[disposition dataUsingEncoding:NSUTF8StringEncoding]];
-
- }
- NSString *body=[NSString stringWithFormat:@"%@Content-Disposition: form-data; name=\"picture\"; filename=\"%@\";Content-Type:video/mpeg4%@",StartBoundary,@"file",Wrap2];
- [totlData appendData:[body dataUsingEncoding:NSUTF8StringEncoding]];
- [totlData appendData:data];
- [totlData appendData:[Wrap1 dataUsingEncoding:NSUTF8StringEncoding]];
- [totlData appendData:[EndBody dataUsingEncoding:NSUTF8StringEncoding]];
-
-
- return totlData;
- }
- /**
- * GET:上传任务 获取上传文件相关信息
- */
- - (void)getFileInfo
- {
- __weak typeof(self) weekSelf = self;
- [self checkParamFromServer:self.fileStream paramCallback:^(NSString * _Nonnull chunkNumName, NSDictionary * _Nullable param) {
- weekSelf.chunkNumName = chunkNumName;
- weekSelf.param = [NSMutableDictionary dictionaryWithDictionary:param];
- [weekSelf startExe];
- }];
- }
- /**
- * POST:上传任务 获取上传文件相关信息
- */
- - (void)startExe{
- HLog(@"del 2024525 暂未做");
- /* hxd del 2024525 暂未做
-
- if (_isSuspendedState) {
- HLog(@"暂停上传");
- [self taskCancel];
- return;
- }
-
- //判断无参数的情况下先将文件信息上传并获得参数
- if (!_param) [self getFileInfo];
- dispatch_group_t group = dispatch_group_create();
- dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
- dispatch_queue_t queue = dispatch_queue_create(NULL, DISPATCH_QUEUE_SERIAL);
-
- if (_fileStream.fileStatus == CWUploadStatusFinished && _successBlock) {
- _successBlock(_fileStream);
- [self sendNotionWithKey:CWUploadTaskExeEnd userInfo:@{@"fileStream":_fileStream}];
- return;
- };
-
- CWStreamFragment *fragment;
- for (NSInteger i=0; i<_fileStream.streamFragments.count; i++) {
- fragment = _fileStream.streamFragments[i];
- if (fragment.fragmentStatus) { // 已上传
- continue;
- }else { // 未上传
- [self->_param setObject:[NSString stringWithFormat:@"%zd",(i+1)] forKey:@"flowChunkNumber"];
- [self->_param setObject:@(fragment.fragmentSize) forKey:@"flowCurrentChunkSize"];
-
- dispatch_group_async(group, queue, ^{
- @autoreleasepool {
- NSData *data = [self->_fileStream readDateOfFragment:fragment];
- self.lastParam = self->_param;
-
- // if ([CWFileUploadManager shardUploadManager].leftStore < data.length) { // 云盘空间不足
- //
- // // 分片上传失败
- // self->_fileStream.fileStatus = CWUploadStatusFailed;
- // self->_fileStream.timeStamp = [iTools getNowTimeStamp];
- // [self archTaskFileStream];
- // // 分片上传失败通知 刷新列表
- // dispatch_async(dispatch_get_main_queue(), ^{
- // NSString *error = @"云盘剩余空间不足";
- // [self sendNotionWithKey:CWUploadTaskExeError userInfo:@{@"fileStream":self->_fileStream,@"error":error}];
- // [self sendNotionWithKey:CloudStoreIsFullNotification userInfo:@{}];
- // });
- // [self deallocSession];
- // return;
- // }
- HLog(@"POST之前——--文件名:%@ 已上传完进度:%.2f 上传状态:%ld", self->_fileStream.fileName, self->_fileStream.progressRate, self->_fileStream.fileStatus);
- [[UseAccountManage shareInstance] doUploadInfoWithParams:self->_param md5string:self->_fileStream.md5String data:data success:^(id _Nonnull responseObject) {
- self->_taskRepeatNum = 0;
- fragment.fragmentStatus = YES;
- [self archTaskFileStream];
- self->_chunkNo = i+1;
-
- dispatch_async(dispatch_get_main_queue(), ^{
- if (self->_fileStream.streamFragments.count == self->_chunkNo) {
- // 分片上传成功 是最后一片 上传完
- self->_fileStream.fileStatus = CWUploadStatusFinished;
- self->_fileStream.progressRate = 1.00;
- self->_fileStream.uploadDateSize = self->_fileStream.fileSize;
- self->_fileStream.timeStamp = [iTools getNowTimeStamp];
- [self archTaskFileStream];
-
- HLog(@"POST之后——--文件名:%@ 已上传完进度:%.2f 上传状态:%ld", self->_fileStream.fileName, self->_fileStream.progressRate, self->_fileStream.fileStatus);
-
- // 上传完成通知 刷新完成列表
- dispatch_async(dispatch_get_main_queue(), ^{
- if (self->_finishBlock) self->_finishBlock(self->_fileStream,nil);
- [self sendNotionWithKey:CWUploadTaskExeEnd userInfo:@{@"fileStream":self->_fileStream}];
- });
-
- }else {
- // 分片上传成功 不是最后一片 上传中
- if (self->_fileStream.uploadDateSize > self->_chunkNo * CWStreamFragmentMaxSize) { // 上传进度异常
- HLog(@"上传进度异常");
- }else {
- // self->_fileStream.fileStatus = CWUploadStatusUpdownloading;
- self->_fileStream.progressRate = self->_chunkNo * 1.00 / self->_fileStream.streamFragments.count;
- self->_fileStream.uploadDateSize = self->_chunkNo * CWStreamFragmentMaxSize;
- self->_fileStream.timeStamp = [iTools getNowTimeStamp];
- [self archTaskFileStream];
-
- HLog(@"POST之后——--文件名:%@ 已上传完进度:%.2f 上传状态:%ld", self->_fileStream.fileName, self->_fileStream.progressRate, self->_fileStream.fileStatus);
-
- // 上传中通知 刷新上传进度
- dispatch_async(dispatch_get_main_queue(), ^{
- if (self->_finishBlock) self->_finishBlock(self->_fileStream,nil);
- [self sendNotionWithKey:CWUploadTaskExeing userInfo:@{@"fileStream":self->_fileStream,@"lastParam":self->_lastParam,@"indexNo":@(self->_chunkNo)}];
- });
- }
- /// 继续GET
- [self getFileInfo];
- }
-
- [self deallocSession];
-
- });
- dispatch_semaphore_signal(semaphore);
- } faild:^(NSError * _Nonnull error) {
-
- if (self->_taskRepeatNum<REPEAT_MAX) { // 分片上传失败 重试3次
-
- self->_taskRepeatNum++;
- [self startExe];
- }else{
- // 分片上传失败
- self->_fileStream.fileStatus = CWUploadStatusFailed;
- // self->_fileStream.progressRate = (self->_chunkNo-1) / self->_fileStream.streamFragments.count;
- // self->_fileStream.uploadDateSize = (self->_chunkNo-1) * CWStreamFragmentMaxSize;
- self->_fileStream.timeStamp = [iTools getNowTimeStamp];
- [self archTaskFileStream];
-
- HLog(@"POST之后——--文件名:%@ 已上传完进度:%.2f 上传状态:%ld", self->_fileStream.fileName, self->_fileStream.progressRate, self->_fileStream.fileStatus);
-
- // 分片上传失败通知 刷新列表
- dispatch_async(dispatch_get_main_queue(), ^{
- if (self->_finishBlock) self->_finishBlock(self->_fileStream,error);
- [self sendNotionWithKey:CWUploadTaskExeError userInfo:@{@"fileStream":self->_fileStream,@"error":error}];
- });
-
- [self deallocSession];
- return;
- }
-
- }];
-
- dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
- }
- });
- break;
- }
- }
-
- dispatch_group_notify(group, queue, ^{
-
- if (self->_fileStream.progressRate != 1) {
- HLog(@"dispatch_group_notify: %.2f", self->_fileStream.progressRate);
- return;
- }
-
- self->_fileStream.fileStatus = CWUploadStatusFinished;
- self->_fileStream.timeStamp = [iTools getNowTimeStamp];
- [self archTaskFileStream];
- dispatch_async(dispatch_get_main_queue(), ^{
- if (self->_finishBlock) self->_finishBlock(self->_fileStream,nil);
- [self sendNotionWithKey:CWUploadTaskExeEnd userInfo:@{@"fileStream":self->_fileStream}];
- });
- [self deallocSession];
- });
- */
- }
- - (void)taskResume{
-
- _isSuspendedState = NO;
- if (self.uploadManager.uploadingTasks.allValues.count >= self.uploadManager.uploadMaxNum) { // 超过最大限制数量3个
-
- self.fileStream.fileStatus = CWUploadStatusWaiting;
- [self archTaskFileStream];
- HLog(@"状态修改——--文件名:%@ 已上传完进度:%.2f 上传状态:%ld", self.fileStream.fileName, self.fileStream.progressRate, self.fileStream.fileStatus);
-
- dispatch_async(dispatch_get_main_queue(), ^{
- if (self->_successBlock) self->_successBlock(self->_fileStream);
- [self sendNotionWithKey:CWUploadTaskExeSuspend userInfo:@{@"fileStream":self->_fileStream}];
- });
- return;
- }else {
-
- self.fileStream.fileStatus = CWUploadStatusUpdownloading;
- [self archTaskFileStream];
- HLog(@"状态修改——--文件名:%@ 已上传完进度:%.2f 上传状态:%ld", self.fileStream.fileName, self.fileStream.progressRate, self.fileStream.fileStatus);
-
- dispatch_async(dispatch_get_main_queue(), ^{
- if (self->_successBlock) self->_successBlock(self->_fileStream);
- [self sendNotionWithKey:CWUploadTaskExeing userInfo:@{@"fileStream":self->_fileStream}];
- });
-
- [self getFileInfo]; // 启动上传任务 先get 后post
- }
-
- }
- - (void)taskCancel{
-
- _fileStream.fileStatus = CWUploadStatusPaused;
- [self archTaskFileStream];
- _isSuspendedState = YES;
-
- dispatch_async(dispatch_get_main_queue(), ^{
- if (self->_finishBlock) self->_finishBlock(self->_fileStream,nil);
- [self sendNotionWithKey:CWUploadTaskExeSuspend userInfo:@{@"fileStream":self->_fileStream}];
- });
- }
- - (void)deallocSession{
- _taskRepeatNum = 0;
- }
- #pragma mark -- tools
- - (void)archTaskFileStream{
-
- NSArray *fileArray = [self->_fileStream.filePath pathComponents];
- NSString *filePathAccount = @"0";
- if (fileArray.count > 3) {
- filePathAccount = fileArray[fileArray.count - 3];
- }
-
- NSArray *plistArray = [[CWFileUploadManager shardUploadManager].plistPath pathComponents];
- NSString *plistPathAccount = @"1";
- if (plistArray.count > 3) {
- plistPathAccount = plistArray[plistArray.count - 3];
- }
-
- // HLog(@"文件缓存账号:%@ 与 plist文件账号:%@", filePathAccount, plistPathAccount);
- if (![filePathAccount isEqualToString:plistPathAccount]) {
- // HLog(@"切换账号 文件缓存账号%@ 与 plist文件账号:%@ 不一致", filePathAccount, plistPathAccount);
- return;
- }
-
- NSMutableDictionary *fsDic = [CWUploadTask unArcherThePlist:[CWFileUploadManager shardUploadManager].plistPath];
- if (!fsDic) {
- fsDic = [NSMutableDictionary dictionary];
- }
- [fsDic setObject:_fileStream forKey:_fileStream.fileName];
- [CWUploadTask archerTheDictionary:fsDic file:[CWFileUploadManager shardUploadManager].plistPath];
- }
- //归档
- + (void)archerTheDictionary:(NSDictionary *)dict file:(NSString *)path{
-
- NSData *data = [NSKeyedArchiver archivedDataWithRootObject:dict];
- BOOL finish = [data writeToFile:path atomically:YES];
- if (finish) {};
-
- }
- //解档
- + (NSMutableDictionary *)unArcherThePlist:(NSString *)path{
- NSMutableDictionary *dic = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
- return dic;
- }
- - (void)sendNotionWithKey:(NSString *)key userInfo:(NSDictionary *)dict{
- //创建通知
- NSNotification *notification =[NSNotification notificationWithName:key object:nil userInfo:dict];
- //通过通知中心发送通知
- [[NSNotificationCenter defaultCenter] postNotification:notification];
-
- }
- @end
|