You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
429 lines
20 KiB
429 lines
20 KiB
// |
|
// WXYZ_ComicDownloadManager.m |
|
// WXReader |
|
// |
|
// Created by Andrew on 2020/3/29. |
|
// Copyright © 2020 Andrew. All rights reserved. |
|
// |
|
|
|
#import "WXYZ_ComicDownloadManager.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_ComicDownloadManager () |
|
|
|
@property (nonatomic, assign) BOOL requesting; |
|
|
|
@property (nonatomic, strong) NSMutableArray *requestOrderArray; |
|
|
|
@end |
|
|
|
@implementation WXYZ_ComicDownloadManager |
|
|
|
implementation_singleton(WXYZ_ComicDownloadManager) |
|
|
|
/* |
|
增 |
|
**/ |
|
|
|
// 下载章节 |
|
- (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 <NSString *>*)chapter_ids |
|
{ |
|
// 作品开始下载标记 |
|
[[WXYZ_DownloadHelper sharedManager] recordDownloadProductionWithProductionModel:productionModel productionType:TFProductionTypeComic]; |
|
|
|
WS(weakSelf) |
|
[TFNetworkTools POST:Comic_Download parameters:@{@"comic_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 comicChaptersRecordDictionaryWithProduction_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 downloadTaskRequestWithProduction_id:production_id]; |
|
} 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:TFProductionTypeComic]; |
|
|
|
// 删除缓存 |
|
[[self comicChaptersRecordDictionaryWithProduction_id:production_id] removeAllObjects]; |
|
|
|
// 写入 |
|
[self comicRecordWriteToPlistWithProduction_id:production_id]; |
|
|
|
return YES; |
|
} |
|
|
|
// 删除本地多个已下载章节 |
|
- (void)removeDownloadChaptersWithProduction_id:(NSInteger)production_id chapter_ids:(NSArray <NSString *> *)chapter_ids |
|
{ |
|
if (chapter_ids.count == 0) { |
|
return; |
|
} |
|
|
|
// 删除文件夹 |
|
[[WXYZ_DownloadHelper sharedManager] removeDownloadChapterFolderWithProduction_id:production_id chapter_ids:chapter_ids productionType:TFProductionTypeComic]; |
|
|
|
// 删除下载记录 |
|
NSMutableDictionary *t_dic = [self comicChaptersRecordDictionaryWithProduction_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 comicRecordWriteToPlistWithProduction_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:TFProductionTypeComic]; |
|
} |
|
|
|
// 获取全部已下载章节model |
|
- (NSArray *)getDownloadChapterModelArrayWithProduction_id:(NSInteger)production_id |
|
{ |
|
NSMutableDictionary *t_dic = [self comicChaptersRecordDictionaryWithProduction_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 comicChaptersRecordDictionaryWithProduction_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 comicChaptersRecordDictionaryWithProduction_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)] isEqual:identify_fail]) { |
|
return WXYZ_ProductionDownloadStateFail; |
|
} |
|
|
|
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:TFProductionTypeComic]; |
|
} |
|
|
|
- (UIImage *)getDownloadLocalImageWithProduction_id:(NSInteger)production_id chapter_id:(NSInteger)chapter_id image_id:(NSInteger)image_id image_update_time:(NSInteger)image_update_time |
|
{ |
|
UIImage *t_image = [UIImage imageWithContentsOfFile:[self chapterImageFilePathWithProduction_id:production_id chapter_id:chapter_id image_id:image_id image_update_time:image_update_time]]; |
|
if (!t_image) { |
|
return nil; |
|
} |
|
return t_image; |
|
} |
|
|
|
- (NSString *)chapterImageFilePathWithProduction_id:(NSInteger)production_id chapter_id:(NSInteger)chapter_id image_id:(NSInteger)image_id image_update_time:(NSInteger)image_update_time |
|
{ |
|
// 章节图片名称 |
|
NSString *imageFileName = [TFUtilsHelper stringToMD5:[NSString stringWithFormat:@"%@%@%@%@", [TFUtilsHelper formatStringWithInteger:production_id], [TFUtilsHelper formatStringWithInteger:chapter_id], [TFUtilsHelper formatStringWithInteger:image_id], [TFUtilsHelper formatStringWithInteger:image_update_time]]]; |
|
|
|
NSString *imageFilePath = @""; |
|
NSArray *extensionArr = @[@"jpeg", @"png", @"gif", @"tiff", @"webp"]; |
|
for (NSString *extension in extensionArr) { |
|
imageFilePath = [[[WXYZ_DownloadHelper sharedManager] getDownloadChapterFolderPathWithProduction_id:production_id chapter_id:chapter_id productionType:TFProductionTypeComic] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", imageFileName, extension]]; |
|
if (imageFilePath && imageFilePath.length > 0 && [[NSFileManager defaultManager] fileExistsAtPath:imageFilePath]) { |
|
return imageFilePath; |
|
} |
|
} |
|
|
|
return imageFilePath; |
|
} |
|
|
|
- (void)downloadTaskRequestWithProduction_id:(NSInteger)production_id |
|
{ |
|
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), ^{ |
|
// 记录出错章节 |
|
NSMutableArray __block *errorChapter = [NSMutableArray array]; |
|
|
|
dispatch_semaphore_t collection_semaphore = dispatch_semaphore_create(0); |
|
|
|
// 记录章节model内容 |
|
NSMutableArray *t_chapterModelArray = [NSMutableArray array]; |
|
|
|
for (NSDictionary *t_dic in taskArray) { |
|
dispatch_queue_t image_queue = dispatch_queue_create("wxyz_image_queue", DISPATCH_QUEUE_CONCURRENT); |
|
dispatch_group_t image_group = dispatch_group_create(); |
|
|
|
TFProductionChapterModel *imageCollectionModel = [TFProductionChapterModel modelWithDictionary:t_dic]; |
|
|
|
if (!imageCollectionModel) { |
|
|
|
// 单个章节下载失败 |
|
dispatch_async(dispatch_get_main_queue(), ^{ |
|
if (weakSelf.downloadChapterStateChangeBlock) { |
|
weakSelf.downloadChapterStateChangeBlock(WXYZ_DownloadStateChapterDownloadFail, imageCollectionModel.production_id, imageCollectionModel.chapter_id); |
|
} |
|
}); |
|
continue; |
|
} |
|
[t_chapterModelArray addObject:imageCollectionModel]; |
|
|
|
// 解析任务 下载一话内的图片组 |
|
for (TFImageListModel *imageModel in imageCollectionModel.image_list) { |
|
dispatch_group_async(image_group, image_queue, ^{ |
|
|
|
dispatch_group_enter(image_group); |
|
|
|
// 创建图片下载器 |
|
AFURLSessionManager *manager = [[AFURLSessionManager alloc] init]; |
|
manager.operationQueue.maxConcurrentOperationCount = 2; |
|
NSURL *URL = [NSURL URLWithString:imageModel.image]; |
|
|
|
NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:[NSURLRequest requestWithURL:URL] progress:nil destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) { |
|
|
|
// 存储文件夹创建 |
|
if (![[NSFileManager defaultManager] fileExistsAtPath:[[WXYZ_DownloadHelper sharedManager] getDownloadChapterFolderPathWithProduction_id:imageCollectionModel.production_id chapter_id:imageCollectionModel.chapter_id productionType:TFProductionTypeComic]]) { |
|
[[NSFileManager defaultManager] createDirectoryAtPath:[[WXYZ_DownloadHelper sharedManager] getDownloadChapterFolderPathWithProduction_id:imageCollectionModel.production_id chapter_id:imageCollectionModel.chapter_id productionType:TFProductionTypeComic] withIntermediateDirectories:YES attributes:nil error:nil]; |
|
} |
|
|
|
// 获取图片名称 |
|
NSString *imageFileName = [TFUtilsHelper stringToMD5:[NSString stringWithFormat:@"%@%@%@%@", [TFUtilsHelper formatStringWithInteger:imageCollectionModel.production_id], [TFUtilsHelper formatStringWithInteger:imageCollectionModel.chapter_id], [TFUtilsHelper formatStringWithInteger:imageModel.image_id], [TFUtilsHelper formatStringWithInteger:imageModel.image_update_time]]]; |
|
|
|
// 图片地址 |
|
NSString *imageFilePath = [[[WXYZ_DownloadHelper sharedManager] getDownloadChapterFolderPathWithProduction_id:imageCollectionModel.production_id chapter_id:imageCollectionModel.chapter_id productionType:TFProductionTypeComic] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", imageFileName, [TFViewHelper imageExtensionWithFormatString:[response MIMEType]]]]; |
|
|
|
return [NSURL fileURLWithPath:imageFilePath]; |
|
} completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) { |
|
// 如果某一张出错就取消下载,删除该章节文件夹 |
|
if (error) { |
|
[errorChapter addObject:[TFUtilsHelper formatStringWithInteger:imageCollectionModel.chapter_id]]; |
|
} |
|
dispatch_group_leave(image_group); |
|
}]; |
|
[downloadTask resume]; |
|
}); |
|
} |
|
dispatch_group_notify(image_group, image_queue, ^{ |
|
|
|
// 删除图片出错章节 |
|
if (errorChapter.count > 0) { |
|
// 删除出错章节文件夹 |
|
[[WXYZ_DownloadHelper sharedManager] removeDownloadChapterFolderWithProduction_id:imageCollectionModel.production_id chapter_ids:errorChapter productionType:TFProductionTypeComic]; |
|
[[weakSelf comicChaptersRecordDictionaryWithProduction_id:imageCollectionModel.production_id] setObject:identify_fail forKey:chapterRecordKey(imageCollectionModel.production_id, imageCollectionModel.chapter_id)]; |
|
[weakSelf comicRecordWriteToPlistWithProduction_id:imageCollectionModel.production_id]; |
|
|
|
// 单个章节下载失败 |
|
dispatch_async(dispatch_get_main_queue(), ^{ |
|
if (weakSelf.downloadChapterStateChangeBlock) { |
|
weakSelf.downloadChapterStateChangeBlock(WXYZ_DownloadStateChapterDownloadFail, imageCollectionModel.production_id, imageCollectionModel.chapter_id); |
|
} |
|
}); |
|
|
|
} else { |
|
|
|
// 下载成功 覆盖临时下载记录 |
|
[[weakSelf comicChaptersRecordDictionaryWithProduction_id:imageCollectionModel.production_id] setObject:imageCollectionModel forKey:chapterRecordKey(imageCollectionModel.production_id, imageCollectionModel.chapter_id)]; |
|
[weakSelf comicRecordWriteToPlistWithProduction_id:imageCollectionModel.production_id]; |
|
|
|
// 单个章节下载完成 |
|
dispatch_async(dispatch_get_main_queue(), ^{ |
|
if (weakSelf.downloadChapterStateChangeBlock) { |
|
weakSelf.downloadChapterStateChangeBlock(WXYZ_DownloadStateChapterDownloadFinished, imageCollectionModel.production_id, imageCollectionModel.chapter_id); |
|
} |
|
}); |
|
} |
|
|
|
|
|
dispatch_semaphore_signal(collection_semaphore); |
|
}); |
|
|
|
dispatch_semaphore_wait(collection_semaphore, DISPATCH_TIME_FOREVER); |
|
} |
|
|
|
dispatch_async(dispatch_get_main_queue(), ^{ |
|
weakSelf.requesting = NO; |
|
if (weakSelf.requestOrderArray.count == 0) { |
|
|
|
// 替换已下载记录章节目录内容 |
|
TFProductionModel *t_productionModel = [[WXYZ_DownloadHelper sharedManager] getDownloadProductionModelWithProduction_id:production_id productionType:TFProductionTypeComic]; |
|
NSMutableArray *t_chapterList = [t_productionModel.chapter_list mutableCopy]; |
|
for (int i = 0; i < t_chapterList.count; i++) { |
|
TFProductionChapterModel *t_chapterModel = [t_chapterList objectAtIndex:i]; |
|
for (TFProductionChapterModel *tt_chapterModel in t_chapterModelArray) { |
|
if (tt_chapterModel.chapter_id == t_chapterModel.chapter_id) { |
|
[t_chapterList replaceObjectAtIndex:i withObject:tt_chapterModel]; |
|
break; |
|
} |
|
} |
|
} |
|
t_productionModel.chapter_list = [t_chapterList copy]; |
|
[[WXYZ_DownloadHelper sharedManager] recordDownloadProductionWithProductionModel:t_productionModel productionType:TFProductionTypeComic]; |
|
|
|
// 任务完成 |
|
if (weakSelf.downloadMissionStateChangeBlock) { |
|
weakSelf.downloadMissionStateChangeBlock(WXYZ_DownloadStateMissionFinished, 0, @[]); |
|
} |
|
} else { |
|
[weakSelf downloadTaskRequestWithProduction_id:production_id]; |
|
} |
|
}); |
|
}); |
|
} |
|
|
|
- (NSMutableArray *)requestOrderArray |
|
{ |
|
if (!_requestOrderArray) { |
|
_requestOrderArray = [NSMutableArray array]; |
|
} |
|
return _requestOrderArray; |
|
} |
|
|
|
- (NSMutableDictionary *)comicChaptersRecordDictionaryWithProduction_id:(NSUInteger)production_id |
|
{ |
|
return [[WXYZ_DownloadHelper sharedManager] chaptersRecordDownloadDictionaryWithProduction_id:production_id productionType:TFProductionTypeComic modelClass:[TFProductionChapterModel class]]; |
|
} |
|
|
|
- (BOOL)comicRecordWriteToPlistWithProduction_id:(NSUInteger)production_id |
|
{ |
|
return [[WXYZ_DownloadHelper sharedManager] writeToChapterPlistFileWithProduction_id:production_id productionType:TFProductionTypeComic modelClass:[TFProductionChapterModel class]]; |
|
} |
|
|
|
@end
|
|
|