// // boxDownloadFileManager.m // 双子星云手机 // // Created by xd h on 2024/5/24. // #import "boxDownloadFileManager.h" @implementation boxDownloadFileManager static boxDownloadFileManager * cur_boxDownloadFileShareInstance = nil; +(boxDownloadFileManager *)shareInstance; { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ cur_boxDownloadFileShareInstance = [[boxDownloadFileManager alloc] init]; }); return cur_boxDownloadFileShareInstance; } - (id)init { self = [super init]; if (self) { //[self initManager]; //某一个YCDownloadItem下载成功通知 [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(downloadTaskFinishedNoti:) name:kDownloadTaskFinishedNoti object:nil]; [self initDownloadManagerFun]; } return self; } - (void)initDownloadManagerFun { NSString *path = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, true).firstObject; path = [path stringByAppendingPathComponent:@"download"]; YCDConfig *config = [YCDConfig new]; config.saveRootPath = path; //config.uid = @"100006"; config.uid = [connectDeviceManager shareInstance].DeviceThirdIdMod.data.sn; HLog(@"%@",config.uid); config.maxTaskCount = 1; config.taskCachekMode = YCDownloadTaskCacheModeKeep;//YCDownloadTaskCacheModeDefault; config.launchAutoResumeDownload = NO; [YCDownloadManager mgrWithConfig:config]; [YCDownloadManager allowsCellularAccess:YES]; [self delItemInDoneTaskFun]; } #pragma mark 删除已经完成和删除文件的任务 - (void)delItemInDoneTaskFun { NSArray *allDownItemArr = [YCDownloadManager downloadList]; for (YCDownloadItem *item in allDownItemArr) { if (item.downloadStatus == YCDownloadStatusFinished) { NSString *savePath = item.savePath; if (![[NSFileManager defaultManager] fileExistsAtPath:savePath]){ [YCDownloadManager stopDownloadWithItem:item]; } } } } #pragma mark 删除多余的任务 比如数据删除了 但是任务还在 - (void)checkDownloadTaskFun{ NSArray *allDownItemArr = [YCDownloadManager downloadList]; NSArray* downloadingArr = nil; NSArray* downloadingFail = nil; if(_databaseArr && _databaseArr.count == 3){ downloadingArr = _databaseArr[0]; downloadingFail = _databaseArr[2]; } for (YCDownloadItem *item in allDownItemArr) { BOOL isNeedStopType = YES; //解码 NSString * urlString = [item.downloadURL stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; if(downloadingArr && downloadingArr.count > 0){ for (ShareFileDataModel*dataModel in downloadingArr) { if([urlString isEqualToString:dataModel.fileUrl]){ isNeedStopType = NO; } } } if(downloadingFail && downloadingFail.count > 0){ for (ShareFileDataModel*dataModel in downloadingFail) { if([urlString isEqualToString:dataModel.fileUrl]){ if(item.downloadedSize >0){ isNeedStopType = NO; } } } } if(isNeedStopType){ HLog(@"停止多的下载任务:%@",item.downloadURL); [YCDownloadManager stopDownloadWithItem:item]; } } } //添加保存记录 - (void)addBoxDownloadRecordFunBy:(NSArray*)arr complete:(custom_complete_B)complete{ if(arr && arr.count >0 ){ //1.排重处理 [self getDataInDatabaseFun:NO complete:^(NSMutableArray * _Nonnull Arr) { [self filterDownloadingTaskFunWithNewTaskArr:arr complete:complete]; }]; } } - (void)filterDownloadingTaskFunWithNewTaskArr:(NSArray*)taskArr complete:(custom_complete_B)complete { NSMutableArray *addTaskArr = [NSMutableArray new]; NSMutableArray * downloadingArr = [NSMutableArray new]; if(_databaseArr && _databaseArr.count == 3){ downloadingArr = _databaseArr[0]; } for (ShareFileDataModel*model in taskArr) { BOOL canAdd = YES; if(downloadingArr.count > 0){ for (ShareFileDataModel*downloadingModel in downloadingArr) { if([downloadingModel.fileUrl isEqualToString:model.fileUrl]){ canAdd = NO; break; } } } if(canAdd){ model.bg_tableName = share_box_download_tableName; [addTaskArr addObject:model]; } } if(addTaskArr.count >0){ KWeakSelf //[ShareFileDataModel bg_saveOrUpdateArray:arr]; [ShareFileDataModel bg_saveOrUpdateArrayAsync:addTaskArr complete:^(BOOL isSuccess) { [weakSelf beginDownloadFilesByUrls:addTaskArr]; complete(isSuccess); }]; } else{//任务下载中 complete(YES); } } #pragma mark 读取数据库数据 - (void)getDataInDatabaseFun:(BOOL)isReGet complete:(custom_complete_Arr)complete { if(_databaseArr && _databaseArr.count == 3 && !isReGet){ complete(_databaseArr); return; } if(!_databaseArr) { _databaseArr = [NSMutableArray new]; } KWeakSelf //dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{ // NSLock *lock = [NSLock new]; // [lock lock]; [ShareFileDataModel bg_findAsync:share_box_download_tableName limit:0 orderBy:nil desc:YES complete:^(NSArray * _Nullable array) { NSMutableArray *failArr = [NSMutableArray new]; NSMutableArray *doneArr = [NSMutableArray new]; NSMutableArray *otherArr = [NSMutableArray new]; if(array && array.count >0){ for (ShareFileDataModel * curModel in array) { if(curModel.downloadBoxStateType == downloadBoxStateFail){ [failArr addObject:curModel]; } else if(curModel.downloadBoxStateType == downloadBoxStateDone){ [doneArr addObject:curModel]; } else{ [otherArr addObject:curModel]; } } } NSLock *lock = [NSLock new]; [lock lock]; NSMutableArray *newArr = [NSMutableArray new]; [newArr addObject:otherArr]; [newArr addObject:doneArr]; [newArr addObject:failArr]; self->_databaseArr = newArr; [lock unlock]; if(isReGet){ [self checkDownloadTaskFun]; } complete(self->_databaseArr); }]; // [lock unlock]; //}); } - (void)handleDatabaseArrByDelete:(ShareFileDataModel*)delModel { if(_databaseArr && _databaseArr.count == 3 ){ if(delModel.downloadBoxStateType == downloadBoxStateDone) { NSMutableArray *arr = _databaseArr[1]; [self deteleModel:delModel inArr:arr]; } else if(delModel.downloadBoxStateType == downloadBoxStateFail){ NSMutableArray *arr = _databaseArr[2]; [self deteleModel:delModel inArr:arr]; } else{ NSMutableArray *arr = _databaseArr[0]; [self deteleModel:delModel inArr:arr]; } } } #pragma mark 处理删除内存数据 - (void)deteleModel:(ShareFileDataModel*)delModel inArr:(NSMutableArray*)delArr{ for (ShareFileDataModel *dataModel in delArr) { if(delModel.bg_id.integerValue == dataModel.bg_id.integerValue){ [delArr removeObject:dataModel]; break; } } } #pragma mark 删除本地数据库记录 - (void)deleteBoxSaveFileRecordBy:(NSMutableArray *)delArr{ NSMutableArray *curDelArr = [NSMutableArray arrayWithArray:delArr]; for (ShareFileDataModel *dataModel in curDelArr) { //1.内存数据删除 [self handleDatabaseArrByDelete:dataModel]; //2.删除数据量 NSMutableString* where = [[NSMutableString alloc] initWithString:@"where "]; NSString *curStr = [NSString stringWithFormat:@"%@=%@ ",bg_sqlKey(@"bg_id"),bg_sqlValue(dataModel.bg_id)]; [where appendString:curStr]; [ShareFileDataModel bg_deleteAsync:share_box_download_tableName where:where complete:^(BOOL isSuccess) { if(isSuccess){ } }]; //3.取消下载 NSString *urlString = dataModel.fileUrl; NSString *requestURLEncodedString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; NSArray *allDownItemArr = [YCDownloadManager itemsWithDownloadUrl:requestURLEncodedString]; for (YCDownloadItem *item in allDownItemArr) { [YCDownloadManager stopDownloadWithItem:item]; } } } #pragma mark 更新本地数据库记录 - (void)updataBoxSaveDataInFailBy:(ShareFileDataModel*)dataModel { //1.修改数据库 if(_databaseArr.count == 3){ NSMutableArray *failArr = _databaseArr[2]; NSMutableArray *ingArr = _databaseArr[0]; for (ShareFileDataModel* model in failArr) { if (dataModel.bg_id.integerValue == model.bg_id.integerValue) { [failArr removeObject:model]; [ingArr addObject:dataModel]; break; } } } [dataModel bg_saveOrUpdateAsync:^(BOOL isSuccess) { }]; } #pragma mark 开始下载文件 - (void)beginDownloadFilesByUrls:(NSArray *)urlArr{ // NSMutableArray*arr = [[SGDownloadManager shareManager] getAllOperation]; // if(arr && arr.count > 0){ // HLog(@"有任务正在下载"); // [[SGDownloadManager shareManager] startAllDownloadTask]; // return; // } if(urlArr && urlArr.count > 0){ for (NSInteger i= urlArr.count-1; i>=0; i--) { ShareFileDataModel *fileModel = urlArr[i]; NSString *urlString = fileModel.fileUrl; NSString *requestURLEncodedString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; YCDownloadItem*item = [YCDownloadItem itemWithUrl:requestURLEncodedString fileId:fileModel.fileName]; //item.extraData = [VideoListInfoModel dateWithInfoModel:model]; [YCDownloadManager startDownloadWithItem:item]; } } } #pragma mark 下载完成 - (void)downloadTaskFinishedNoti:(NSNotification *)notification { YCDownloadItem *item = notification.object; if(!item)return; if (item.downloadStatus == YCDownloadStatusFinished) { [self handldDownloadDoneDataBy:item]; } else if (item.downloadStatus == YCDownloadStatusFailed){ [self handldDownloadFailDataBy:item]; } dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ [[NSNotificationCenter defaultCenter] postNotificationName:nasDownloadTaskFinishedNotification object:item]; }); } #pragma mark 下载完成数据回调处理 - (void)handldDownloadDoneDataBy:(YCDownloadItem*)item { //解码 NSString * urlString = [item.downloadURL stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; if(_databaseArr && _databaseArr.count == 3 ){ NSMutableArray *ingArr = _databaseArr[0]; for (ShareFileDataModel*dataModel in ingArr) { HLog(@"22222222 %@\n%@",urlString,dataModel.fileUrl); if([urlString isEqualToString:dataModel.fileUrl]){ dataModel.downloadBoxStateType = downloadBoxStateDone; NSMutableArray *doneArr = _databaseArr[1]; [doneArr insertObject:dataModel atIndex:0]; //更新数据库 [dataModel bg_saveOrUpdateAsync:^(BOOL isSuccess) { }]; [self deteleModel:dataModel inArr:ingArr]; break; } } } } #pragma mark 下载失败数据回调处理 - (void)handldDownloadFailDataBy:(YCDownloadItem*)item { //解码 NSString * urlString = [item.downloadURL stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; if(_databaseArr && _databaseArr.count == 3 ){ NSMutableArray *ingArr = _databaseArr[0]; for (ShareFileDataModel*dataModel in ingArr) { HLog(@"22222222 %@\n%@",urlString,dataModel.fileUrl); if([urlString isEqualToString:dataModel.fileUrl]){ [self handleDatabaseArrByDelete:dataModel]; dataModel.downloadBoxStateType = downloadBoxStateFail; dataModel.failMsg = NSLocalizedString(@"File_download_error_404",nil); NSMutableArray *failArr = _databaseArr[2]; [failArr insertObject:dataModel atIndex:0]; //更新数据库 [dataModel bg_saveOrUpdateAsync:^(BOOL isSuccess) { }]; break; } } } } #pragma mark 全部暂停 或者暂停某一个 - (void)suspendDownloadFileFun:(BOOL)isSuspendAll withModel:(ShareFileDataModel*)dataModel withItem:(YCDownloadItem*)item { if(isSuspendAll){//全部暂停 if (_databaseArr && _databaseArr.count == 3) { NSMutableArray *downloadingArr = _databaseArr[0]; for (ShareFileDataModel*model in downloadingArr) { model.downloadBoxStateType = downloadBoxStateSuspend; } if(downloadingArr.count > 0){ [ShareFileDataModel bg_updateArrayAsync:downloadingArr complete:^(BOOL isSuccess) { }]; } } [YCDownloadManager pauseAllDownloadTask]; } else if(dataModel){//暂停指定任务 NSString *urlString = dataModel.fileUrl; NSString *requestURLEncodedString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; HLog(@"%@",urlString); if(item && [item.downloadURL isEqualToString:requestURLEncodedString]){ [YCDownloadManager pauseDownloadWithItem:item]; } else{ NSArray *allDownItemArr = [YCDownloadManager itemsWithDownloadUrl:requestURLEncodedString]; if(allDownItemArr.count == 1){ YCDownloadItem *item = allDownItemArr.firstObject; [YCDownloadManager pauseDownloadWithItem:item]; } else{ HLog(@"%ld\n%@",allDownItemArr.count,allDownItemArr); for (YCDownloadItem *item in allDownItemArr) { if (item.downloadStatus == YCDownloadStatusFinished) {//这里有问题 [YCDownloadManager stopDownloadWithItem:item]; } else{ [YCDownloadManager pauseDownloadWithItem:item]; } } } } //2.修改状态 if (_databaseArr && _databaseArr.count == 3) { NSMutableArray *downloadingArr = _databaseArr[0]; for (ShareFileDataModel*model in downloadingArr) { if(model.bg_id.integerValue == dataModel.bg_id.integerValue){ model.downloadBoxStateType = downloadBoxStateSuspend; break; } } if(downloadingArr.count > 0){ [ShareFileDataModel bg_updateArrayAsync:downloadingArr complete:^(BOOL isSuccess) { }]; } } } } #pragma mark 重新开始下载 - (void)reDownloadFileFunBy:(NSMutableArray*)arr withAll:(BOOL)isAllType withItem:(YCDownloadItem*)item { if(isAllType){ //[YCDownloadManager resumeAllDownloadTask]; NSArray *allDownItemArr = [YCDownloadManager downloadList]; for (YCDownloadItem *item in allDownItemArr) { if (item.downloadStatus != YCDownloadStatusFailed && item.downloadStatus != YCDownloadStatusFinished) { //[YCDownloadManager startDownloadWithItem:item]; [YCDownloadManager resumeDownloadWithItem:item]; } } if (_databaseArr && _databaseArr.count == 3) { NSMutableArray *downloadingArr = _databaseArr[0]; for (ShareFileDataModel*model in downloadingArr) { model.downloadBoxStateType = downloadBoxStateDownloadloading; } if(downloadingArr.count > 0){ [ShareFileDataModel bg_updateArrayAsync:downloadingArr complete:^(BOOL isSuccess) { }]; } } } else{ ShareFileDataModel* dataModel = nil; if(arr && arr.count > 0){ dataModel = arr.firstObject; //修改数据库状态 dataModel.downloadBoxStateType = downloadBoxStateDownloadloading; [ShareFileDataModel bg_updateArrayAsync:@[dataModel] complete:^(BOOL isSuccess) { }]; }else{ return; } NSString *urlString = dataModel.fileUrl; NSString *requestURLEncodedString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; HLog(@"%@",urlString); if (item && [item.downloadURL isEqualToString:requestURLEncodedString]) { [YCDownloadManager resumeDownloadWithItem:item]; } else { NSArray *allDownItemArr = [YCDownloadManager itemsWithDownloadUrl:requestURLEncodedString]; if(allDownItemArr.count == 0){ [self beginDownloadFilesByUrls:arr]; } else if(allDownItemArr.count == 1){ YCDownloadItem *item = allDownItemArr.firstObject; [YCDownloadManager resumeDownloadWithItem:item]; } else{ for (YCDownloadItem *item in allDownItemArr) { if (item.downloadStatus != YCDownloadStatusFinished) { [YCDownloadManager resumeDownloadWithItem:item]; } else{ [YCDownloadManager stopDownloadWithItem:item]; } } } } } } @end