// // WXYZ_AudioDownloadManager.m // WXReader // // Created by Andrew on 2020/3/28. // Copyright © 2020 Andrew. All rights reserved. // #import "WXYZ_AudioDownloadManager.h" static dispatch_group_t url_session_manager_completion_group() { static dispatch_group_t af_url_session_manager_completion_group; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ af_url_session_manager_completion_group = dispatch_group_create(); }); return af_url_session_manager_completion_group; } @interface WXYZ_AudioDownloadManager () @property (nonatomic, assign) BOOL requesting; @property (nonatomic, strong) NSMutableArray *requestOrderArray; @end @implementation WXYZ_AudioDownloadManager implementation_singleton(WXYZ_AudioDownloadManager) /* 增 **/ // 下载章节 - (void)downloadChapterWithProductionModel:(TFProductionModel *)productionModel production_id:(NSInteger)production_id chapter_id:(NSInteger)chapter_id { [self downloadChaptersWithProductionModel:productionModel production_id:production_id chapter_ids:@[[TFUtilsHelper formatStringWithInteger:chapter_id]]]; } // 下载多个章节 - (void)downloadChaptersWithProductionModel:(TFProductionModel *)productionModel production_id:(NSInteger)production_id chapter_ids:(NSArray *)chapter_ids { [[WXYZ_DownloadHelper sharedManager] recordDownloadProductionWithProductionModel:productionModel productionType:TFProductionTypeAudio]; WS(weakSelf) [TFNetworkTools POST:Audio_Chapter_Download parameters:@{@"audio_id":[TFUtilsHelper formatStringWithInteger:production_id], @"chapter_id":[chapter_ids componentsJoinedByString:@","]} model:nil success:^(BOOL isSuccess, NSDictionary * _Nullable t_model, TFNetworkRequestModel * _Nonnull requestModel) { if (isSuccess) { dispatch_async(dispatch_get_main_queue(), ^{ // 任务开始 if (weakSelf.downloadMissionStateChangeBlock) { weakSelf.downloadMissionStateChangeBlock(WXYZ_DownloadStateMissionStart, production_id, chapter_ids); } // 任务加入任务队列 NSArray *taskArray = [t_model objectForKey:@"data"]; if (taskArray.count > 0) { for (NSDictionary *t_dic in taskArray) { TFProductionChapterModel *imageCollectionModel = [TFProductionChapterModel modelWithDictionary:t_dic]; if (imageCollectionModel) { // 开始下载 [[self audioChaptersRecordDictionaryWithProduction_id:imageCollectionModel.production_id] setObject:identify_downloading forKey:chapterRecordKey(imageCollectionModel.production_id, imageCollectionModel.chapter_id)]; dispatch_async(dispatch_get_main_queue(), ^{ if (self.downloadChapterStateChangeBlock) { self.downloadChapterStateChangeBlock(WXYZ_DownloadStateChapterDownloadStart, imageCollectionModel.production_id, imageCollectionModel.chapter_id); } }); } } [weakSelf.requestOrderArray addObject:taskArray]; if (!weakSelf.requesting) { [TFPromptManager showPromptViewWithStatus:TFPromptStatusSuccess promptTitle:TFLocalizedString(@"已加入下载列表")]; } // 开始下载任务 [weakSelf downloadTaskRequest]; } else { // 任务失败 if (weakSelf.downloadMissionStateChangeBlock) { weakSelf.downloadMissionStateChangeBlock(WXYZ_DownloadStateMissionFail, production_id, chapter_ids); } } }); } else if (Compare_Json_isEqualTo(requestModel.code, 701)) { // 请求购买 // 任务失败 dispatch_async(dispatch_get_main_queue(), ^{ if (weakSelf.downloadMissionStateChangeBlock) { weakSelf.downloadMissionStateChangeBlock(WXYZ_DownloadStateMissionShouldPay, production_id, chapter_ids); } }); } else { [TFPromptManager showPromptViewWithStatus:TFPromptStatusError promptTitle:requestModel.msg]; // 任务失败 dispatch_async(dispatch_get_main_queue(), ^{ if (weakSelf.downloadMissionStateChangeBlock) { weakSelf.downloadMissionStateChangeBlock(WXYZ_DownloadStateMissionFail, production_id, chapter_ids); } }); } } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { // 任务失败 dispatch_async(dispatch_get_main_queue(), ^{ if (weakSelf.downloadMissionStateChangeBlock) { weakSelf.downloadMissionStateChangeBlock(WXYZ_DownloadStateMissionFail, production_id, chapter_ids); } }); }]; } /* 删 **/ // 删除本地已下载作品 - (BOOL)removeDownloadProductionWithProduction_id:(NSInteger)production_id { // 删除作品文件夹 [[WXYZ_DownloadHelper sharedManager] removeDownloadProductionFolderWithProduction_id:production_id productionType:TFProductionTypeAudio]; // 删除缓存 [[self audioChaptersRecordDictionaryWithProduction_id:production_id] removeAllObjects]; // 写入 [self audioRecordWriteToPlistWithProduction_id:production_id]; return YES; } // 删除本地多个已下载章节 - (void)removeDownloadChaptersWithProduction_id:(NSInteger)production_id chapter_ids:(NSArray *)chapter_ids { if (chapter_ids.count == 0) { return; } // 删除文件夹 [[WXYZ_DownloadHelper sharedManager] removeDownloadChapterFolderWithProduction_id:production_id chapter_ids:chapter_ids productionType:TFProductionTypeAudio]; // 删除下载记录 NSMutableDictionary *t_dic = [self audioChaptersRecordDictionaryWithProduction_id:production_id]; NSMutableArray *t_delete_arr = [NSMutableArray array]; for (NSString *chapter_id in chapter_ids) { [t_delete_arr addObject:chapterRecordKey(production_id, [chapter_id integerValue])]; } [t_dic removeObjectsForKeys:t_delete_arr]; // 如果全部章节已经删除,则删除整体作品文件夹 if ([self getDownloadChapterCountWithProduction_id:production_id] == 0) { [self removeDownloadProductionWithProduction_id:production_id]; } else { [self audioRecordWriteToPlistWithProduction_id:production_id]; } // 删除回调 dispatch_async(dispatch_get_main_queue(), ^{ if (self.downloadDeleteFinishBlock) { self.downloadDeleteFinishBlock(chapter_ids, @[]); } }); } /* 查 **/ // 获取下载章节数 - (NSInteger)getDownloadChapterCountWithProduction_id:(NSInteger)production_id { return [[WXYZ_DownloadHelper sharedManager] getDownloadChapterCountWithProduction_id:production_id productionType:TFProductionTypeAudio]; } // 获取全部已下载章节model - (NSArray *)getDownloadChapterModelArrayWithProduction_id:(NSInteger)production_id { NSMutableDictionary *t_dic = [self audioChaptersRecordDictionaryWithProduction_id:production_id]; NSMutableArray *t_arr = [NSMutableArray array]; for (id value in t_dic.allValues) { if ([value isKindOfClass:[TFProductionChapterModel class]]) { [t_arr addObject:value]; } } return [t_arr copy]; } // 获取已下载章节model - (id)getDownloadChapterModelWithProduction_id:(NSInteger)production_id chapter_id:(NSInteger)chapter_id { NSMutableDictionary *t_dic = [self audioChaptersRecordDictionaryWithProduction_id:production_id]; id value = [t_dic objectForKey:chapterRecordKey(production_id, chapter_id)]; if ([value isKindOfClass:[TFProductionChapterModel class]]) { return value; } return nil; } // 获取章节下载状态 - (WXYZ_ProductionDownloadState)getChapterDownloadStateWithProduction_id:(NSInteger)production_id chapter_id:(NSInteger)chapter_id { NSMutableDictionary *t_dic = [self audioChaptersRecordDictionaryWithProduction_id:production_id]; if ([[t_dic objectForKey:chapterRecordKey(production_id, chapter_id)] isEqual:identify_downloading]) { return WXYZ_ProductionDownloadStateDownloading; } if ([[t_dic objectForKey:chapterRecordKey(production_id, chapter_id)] isKindOfClass:[TFProductionChapterModel class]]) { return WXYZ_ProductionDownloadStateDownloaded; } return WXYZ_ProductionDownloadStateNormal; } // 作品章节是否下载 - (BOOL)isChapterDownloadedWithProduction_id:(NSInteger)production_id chapter_id:(NSInteger)chapter_id { return [[WXYZ_DownloadHelper sharedManager] isChapterDownloadedWithProduction_id:production_id chapter_id:chapter_id productionType:TFProductionTypeAudio]; } // 获取文件地址 - (NSString *)chapterDownloadedFilePathWithProduction_id:(NSInteger)production_id chapter_id:(NSInteger)chapter_id chapter_update_time:(NSString *)chapter_update_time { // 章节文件名称 NSString *chapterFileName = [TFUtilsHelper stringToMD5:[NSString stringWithFormat:@"%@%@%@", [TFUtilsHelper formatStringWithInteger:production_id], [TFUtilsHelper formatStringWithInteger:chapter_id], [TFUtilsHelper formatStringWithObject:chapter_update_time]]]; NSString *chapterFilePath = @""; NSArray *extensionArr = @[@"mp3", @"wav", @"wma"]; for (NSString *extension in extensionArr) { chapterFilePath = [[[WXYZ_DownloadHelper sharedManager] getDownloadChapterFolderPathWithProduction_id:production_id chapter_id:chapter_id productionType:TFProductionTypeAudio] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", chapterFileName, extension]]; if (chapterFilePath && chapterFilePath.length > 0 && [[NSFileManager defaultManager] fileExistsAtPath:chapterFilePath]) { return chapterFilePath; } } return chapterFilePath; } - (void)downloadTaskRequest { if (self.requestOrderArray.count == 0) { return; } if (self.requesting) { return; } self.requesting = YES; NSArray *taskArray = [self.requestOrderArray firstObject]; [self.requestOrderArray removeFirstObject]; WS(weakSelf) dispatch_group_async(url_session_manager_completion_group(), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ dispatch_queue_t audio_queue = dispatch_queue_create("wxyz_audio_queue", DISPATCH_QUEUE_CONCURRENT); dispatch_group_t audio_group = dispatch_group_create(); for (NSDictionary *t_dic in taskArray) { dispatch_group_async(audio_group, audio_queue, ^{ dispatch_group_enter(audio_group); TFProductionChapterModel *t_model = [TFProductionChapterModel modelWithDictionary:t_dic]; if (!t_model) { // 单个章节下载失败 dispatch_async(dispatch_get_main_queue(), ^{ if (weakSelf.downloadChapterStateChangeBlock) { weakSelf.downloadChapterStateChangeBlock(WXYZ_DownloadStateChapterDownloadFail, t_model.production_id, t_model.chapter_id); } }); } AFURLSessionManager *manager = [[AFURLSessionManager alloc] init]; manager.operationQueue.maxConcurrentOperationCount = 2; NSURL *URL = [NSURL URLWithString:t_model.content]; NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:[NSURLRequest requestWithURL:URL] progress:nil destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) { // 存储文件夹创建 if (![[NSFileManager defaultManager] fileExistsAtPath:[[WXYZ_DownloadHelper sharedManager] getDownloadChapterFolderPathWithProduction_id:t_model.production_id chapter_id:t_model.chapter_id productionType:TFProductionTypeAudio]]) { [[NSFileManager defaultManager] createDirectoryAtPath:[[WXYZ_DownloadHelper sharedManager] getDownloadChapterFolderPathWithProduction_id:t_model.production_id chapter_id:t_model.chapter_id productionType:TFProductionTypeAudio] withIntermediateDirectories:YES attributes:nil error:nil]; } // 获取图片名称 NSString *audioFileName = [TFUtilsHelper stringToMD5:[NSString stringWithFormat:@"%@%@%@", [TFUtilsHelper formatStringWithInteger:t_model.production_id], [TFUtilsHelper formatStringWithInteger:t_model.chapter_id], [TFUtilsHelper formatStringWithObject:t_model.update_time]]]; // 图片地址 NSString *audioFilePath = [[[WXYZ_DownloadHelper sharedManager] getDownloadChapterFolderPathWithProduction_id:t_model.production_id chapter_id:t_model.chapter_id productionType:TFProductionTypeAudio] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", audioFileName, [TFViewHelper audioExtensionWithFormatString:[response MIMEType]]]]; return [NSURL fileURLWithPath:audioFilePath]; } completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) { if (error) { // 删除出错章节文件夹 [[WXYZ_DownloadHelper sharedManager] removeDownloadChapterFolderWithProduction_id:t_model.production_id chapter_ids:@[[TFUtilsHelper formatStringWithInteger:t_model.chapter_id]] productionType:TFProductionTypeAudio]; [[weakSelf audioChaptersRecordDictionaryWithProduction_id:t_model.production_id] setObject:identify_fail forKey:chapterRecordKey(t_model.production_id, t_model.chapter_id)]; [weakSelf audioRecordWriteToPlistWithProduction_id:t_model.production_id]; // 章节下载失败 dispatch_async(dispatch_get_main_queue(), ^{ if (weakSelf.downloadChapterStateChangeBlock) { weakSelf.downloadChapterStateChangeBlock(WXYZ_DownloadStateChapterDownloadFail, t_model.production_id, t_model.chapter_id); } }); } else { // 下载成功 覆盖临时下载记录 [[weakSelf audioChaptersRecordDictionaryWithProduction_id:t_model.production_id] setObject:t_model forKey:chapterRecordKey(t_model.production_id, t_model.chapter_id)]; [weakSelf audioRecordWriteToPlistWithProduction_id:t_model.production_id]; // 章节下载成功 dispatch_async(dispatch_get_main_queue(), ^{ if (weakSelf.downloadChapterStateChangeBlock) { weakSelf.downloadChapterStateChangeBlock(WXYZ_DownloadStateChapterDownloadFinished, t_model.production_id, t_model.chapter_id); } }); } dispatch_group_leave(audio_group); }]; [downloadTask resume]; }); } dispatch_group_notify(audio_group, audio_queue, ^{ dispatch_async(dispatch_get_main_queue(), ^{ weakSelf.requesting = NO; if (weakSelf.requestOrderArray.count == 0) { // 任务完成 if (weakSelf.downloadMissionStateChangeBlock) { weakSelf.downloadMissionStateChangeBlock(WXYZ_DownloadStateMissionFinished, 0, @[]); } } else { [weakSelf downloadTaskRequest]; } }); }); }); } - (NSMutableArray *)requestOrderArray { if (!_requestOrderArray) { _requestOrderArray = [NSMutableArray array]; } return _requestOrderArray; } - (NSMutableDictionary *)audioChaptersRecordDictionaryWithProduction_id:(NSUInteger)production_id { return [[WXYZ_DownloadHelper sharedManager] chaptersRecordDownloadDictionaryWithProduction_id:production_id productionType:TFProductionTypeAudio modelClass:[TFProductionChapterModel class]]; } - (BOOL)audioRecordWriteToPlistWithProduction_id:(NSUInteger)production_id { return [[WXYZ_DownloadHelper sharedManager] writeToChapterPlistFileWithProduction_id:production_id productionType:TFProductionTypeAudio modelClass:[TFProductionChapterModel class]]; } @end