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.
376 lines
19 KiB
376 lines
19 KiB
// |
|
// WXYZ_DownloadHelper.m |
|
// WXReader |
|
// |
|
// Created by Andrew on 2020/4/1. |
|
// Copyright © 2020 Andrew. All rights reserved. |
|
// |
|
|
|
/* 下载缓存结构示意 |
|
WXYZ_DownloadFileFolder ━┳━ BookDownloadFileFolder ━┳━ WXYZ_DownloadProductionRecordFile.plist |
|
┃ ┃ |
|
┃ ┃ |
|
┃ ┣━ 作品文件夹(production_id) ━┳━ WXYZ_DownloadChapterRecordFile.plist |
|
┃ ┃ ┃ |
|
┃ ┃ ┃ |
|
┃ ┃ ┣━ 章节文件夹(production_id + chapter_id) ━━ 对应文件 比如.txt/.jpg/.png/.mp3 |
|
┃ ┃ ┃ |
|
┃ ┃ ┃ |
|
┃ ┃ ┗━ 章节文件夹(production_id + chapter_id) ━━ 对应文件 比如.txt/.jpg/.png/.mp3 |
|
┃ ┃ |
|
┃ ┗━ 作品文件夹(production_id) |
|
┃ |
|
┃ |
|
┣━ ComicDownloadFileFolder ━┳━ WXYZ_DownloadProductionRecordFile.plist |
|
┃ ┃ |
|
┃ ┃ |
|
┃ ┣━ 作品文件夹(production_id) ━┳━ WXYZ_DownloadChapterRecordFile.plist |
|
┃ ┃ ┃ |
|
┃ ┃ ┃ |
|
┃ ┃ ┣━ 章节文件夹(production_id + chapter_id) ━━ 对应文件 比如.txt/.jpg/.png/.mp3 |
|
┃ ┃ ┃ |
|
┃ ┃ ┃ |
|
┃ ┃ ┗━ 章节文件夹(production_id + chapter_id) ━━ 对应文件 比如.txt/.jpg/.png/.mp3 |
|
┃ ┃ |
|
┃ ┗━ 作品文件夹(production_id) |
|
┃ |
|
┗━ AudioDownloadFileFolder ━┳━ WXYZ_DownloadProductionRecordFile.plist |
|
┃ |
|
┃ |
|
┣━ 作品文件夹(production_id) ━┳━ WXYZ_DownloadChapterRecordFile.plist |
|
┃ ┃ |
|
┃ ┃ |
|
┃ ┣━ 章节文件夹(production_id + chapter_id) ━━ 对应文件 比如.txt/.jpg/.png/.mp3 |
|
┃ ┃ |
|
┃ ┃ |
|
┃ ┗━ 章节文件夹(production_id + chapter_id) ━━ 对应文件 比如.txt/.jpg/.png/.mp3 |
|
┃ |
|
┗━ 作品文件夹(production_id) |
|
|
|
*/ |
|
|
|
|
|
#import "WXYZ_DownloadHelper.h" |
|
|
|
@implementation WXYZ_DownloadHelper |
|
|
|
implementation_singleton(WXYZ_DownloadHelper) |
|
|
|
// 作品下载记录 |
|
- (void)recordDownloadProductionWithProductionModel:(TFProductionModel *)productionModel productionType:(TFProductionType)productionType |
|
{ |
|
if (!productionModel) { |
|
return; |
|
} |
|
|
|
NSMutableArray *t_arr = [self productionRecordDownloadArrayWithProductionType:productionType]; |
|
for (TFProductionModel *t_model in t_arr) { |
|
if (t_model.production_id == productionModel.production_id) { |
|
return; |
|
} |
|
} |
|
|
|
[[self productionRecordDownloadArrayWithProductionType:productionType] addObject:productionModel]; |
|
[self writeToPlistFileWithProductionType:productionType]; |
|
} |
|
|
|
// 删除作品下载记录 |
|
- (void)removeRecordDownloadProductionWithProduction_id:(NSInteger)production_id productionType:(TFProductionType)productionType |
|
{ |
|
NSMutableArray *t_arr = [[self productionRecordDownloadArrayWithProductionType:productionType] mutableCopy]; |
|
for (TFProductionModel *t_model in t_arr) { |
|
if (t_model.production_id == production_id) { |
|
[[self productionRecordDownloadArrayWithProductionType:productionType] removeObject:t_model]; |
|
[self writeToPlistFileWithProductionType:productionType]; |
|
return; |
|
} |
|
} |
|
} |
|
|
|
// 删除章节下载记录(返回是否成功,如果成功那么需要在对应的downloadManager中,重置记录变量,从本地重新获取) |
|
- (BOOL)removeRecordDownloadChapterWithProduction_id:(NSInteger)production_id chapter_ids:(NSArray <NSString *>*)chapter_ids productionType:(TFProductionType)productionType |
|
{ |
|
NSMutableDictionary *localCacheDic = [NSMutableDictionary dictionaryWithContentsOfFile:[[WXYZ_DownloadHelper sharedManager] getDownloadChapterRecordPlistFilePathWithProduction_id:production_id productionType:productionType]]; |
|
for (NSString *chapter_id in chapter_ids) { |
|
[localCacheDic removeObjectForKey:chapterRecordKey(production_id, [chapter_id integerValue])]; |
|
} |
|
|
|
NSMutableDictionary *save_dic = [NSMutableDictionary dictionary]; |
|
for (NSString *key in localCacheDic.allKeys) { |
|
|
|
id value = [localCacheDic objectForKey:key]; |
|
|
|
if ([value isKindOfClass:[NSClassFromString(@"WXYZ_ComicReaderModel") class]]) { |
|
value = [value modelToJSONString]; |
|
} |
|
[save_dic setObject:value forKey:key]; |
|
} |
|
|
|
// 写入文件 |
|
if (![save_dic writeToFile:[self getDownloadChapterRecordPlistFilePathWithProduction_id:production_id productionType:productionType] atomically:NO]) { |
|
return NO; |
|
} |
|
return YES; |
|
} |
|
|
|
// 删除作品文件夹 |
|
- (void)removeDownloadProductionFolderWithProduction_id:(NSInteger)production_id productionType:(TFProductionType)productionType |
|
{ |
|
// 删除plist文件记录 |
|
[self removeRecordDownloadProductionWithProduction_id:production_id productionType:productionType]; |
|
|
|
// 删除对应作品整体文件夹 |
|
[[NSFileManager defaultManager] removeItemAtPath:[self getDownloadProductionFolderPathWithProduction_id:production_id productionType:productionType] error:nil]; |
|
} |
|
|
|
// 删除章节文件夹 |
|
- (BOOL)removeDownloadChapterFolderWithProduction_id:(NSInteger)production_id chapter_ids:(NSArray <NSString *>*)chapter_ids productionType:(TFProductionType)productionType |
|
{ |
|
for (NSString *chapter_id in chapter_ids) { |
|
if ([[NSFileManager defaultManager] fileExistsAtPath:[self getDownloadChapterFolderPathWithProduction_id:production_id chapter_id:[chapter_id integerValue] productionType:productionType]]) { |
|
[[NSFileManager defaultManager] removeItemAtPath:[self getDownloadChapterFolderPathWithProduction_id:production_id chapter_id:[chapter_id integerValue] productionType:productionType] error:nil]; |
|
} |
|
} |
|
|
|
// 删除章节plist文件记录 |
|
return [self removeRecordDownloadChapterWithProduction_id:production_id chapter_ids:chapter_ids productionType:productionType]; |
|
} |
|
|
|
// 作品章节是否下载 |
|
- (BOOL)isChapterDownloadedWithProduction_id:(NSInteger)production_id chapter_id:(NSInteger)chapter_id productionType:(TFProductionType)productionType |
|
{ |
|
if ([[NSFileManager defaultManager] contentsOfDirectoryAtPath:[self getDownloadChapterFolderPathWithProduction_id:production_id chapter_id:chapter_id productionType:productionType] error:nil].count > 0) { |
|
return YES; |
|
} |
|
return NO; |
|
} |
|
|
|
// 获取下载章节数 |
|
- (NSInteger)getDownloadChapterCountWithProduction_id:(NSInteger)production_id productionType:(TFProductionType)productionType |
|
{ |
|
// 存在已下载章节内容文件夹数量 |
|
CGFloat chapterDownloadNumber = 0; |
|
|
|
// 获取作品下全部章节文件夹名称 |
|
NSArray <NSString *>*chapterFolderNames = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:[self getDownloadProductionFolderPathWithProduction_id:production_id productionType:productionType] error:nil]; |
|
|
|
for (NSString *folderName in chapterFolderNames) { |
|
NSString *chapterFloderPath = [[self getDownloadProductionFolderPathWithProduction_id:production_id productionType:productionType] stringByAppendingPathComponent:folderName]; |
|
|
|
BOOL isDirectory = NO; |
|
[[NSFileManager defaultManager] fileExistsAtPath:chapterFloderPath isDirectory:&isDirectory]; |
|
if (isDirectory && [[NSFileManager defaultManager] contentsOfDirectoryAtPath:chapterFloderPath error:nil].count > 0) { |
|
chapterDownloadNumber ++; |
|
} |
|
} |
|
|
|
return chapterDownloadNumber; |
|
} |
|
|
|
// 获取类别下的所有下载作品 |
|
- (NSArray <TFProductionModel *> *)getDownloadProductionArrayWithProductionType:(TFProductionType)productionType |
|
{ |
|
return [self productionRecordDownloadArrayWithProductionType:productionType]; |
|
} |
|
|
|
- (TFProductionModel *)getDownloadProductionModelWithProduction_id:(NSInteger)production_id productionType:(TFProductionType)productionType |
|
{ |
|
for (TFProductionModel *t_model in [self productionRecordDownloadArrayWithProductionType:productionType]) { |
|
if (t_model.production_id == production_id) { |
|
return t_model; |
|
} |
|
} |
|
return nil; |
|
} |
|
|
|
// 主文件夹路径 |
|
- (NSString *)getDownloadRootFolderPathWithProductionType:(TFProductionType)productionType |
|
{ |
|
NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectOrNilAtIndex:0]; |
|
|
|
// 主目录文件夹 |
|
NSString *rootFolderPath = [documentPath stringByAppendingPathComponent:[TFUtilsHelper stringToMD5:@"WXYZ_DownloadFileFolder"]]; |
|
|
|
// 创建章节文件夹 |
|
if (![[NSFileManager defaultManager] fileExistsAtPath:rootFolderPath]) { |
|
[[NSFileManager defaultManager] createDirectoryAtPath:rootFolderPath withIntermediateDirectories:YES attributes:nil error:nil]; |
|
} |
|
|
|
// 作品类别文件夹 |
|
NSString *typeFolderPath = @""; |
|
switch (productionType) { |
|
case TFProductionTypeNovel: // 存储全部下载书籍 |
|
typeFolderPath = [rootFolderPath stringByAppendingPathComponent:[TFUtilsHelper stringToMD5:@"BookDownloadFileFolder"]]; |
|
break; |
|
case TFProductionTypeComic: // 存储全部下载漫画 |
|
typeFolderPath = [rootFolderPath stringByAppendingPathComponent:[TFUtilsHelper stringToMD5:@"ComicDownloadFileFolder"]]; |
|
break; |
|
case TFProductionTypeAudio: // 存储全部下载听书 |
|
typeFolderPath = [rootFolderPath stringByAppendingPathComponent:[TFUtilsHelper stringToMD5:@"AudioDownloadFileFolder"]]; |
|
break; |
|
|
|
default: |
|
break; |
|
} |
|
|
|
// 创建章节文件夹 |
|
if (![[NSFileManager defaultManager] fileExistsAtPath:typeFolderPath]) { |
|
[[NSFileManager defaultManager] createDirectoryAtPath:typeFolderPath withIntermediateDirectories:YES attributes:nil error:nil]; |
|
} |
|
|
|
return typeFolderPath; |
|
} |
|
|
|
// 下载作品文件夹 |
|
- (NSString *)getDownloadProductionFolderPathWithProduction_id:(NSInteger)production_id productionType:(TFProductionType)productionType |
|
{ |
|
NSString *productionFolderPath = [[self getDownloadRootFolderPathWithProductionType:productionType] stringByAppendingPathComponent:[TFUtilsHelper stringToMD5:[NSString stringWithFormat:@"%@%@", [TFUtilsHelper formatStringWithInteger:productionType], [TFUtilsHelper formatStringWithInteger:production_id]]]]; |
|
// 创建章节文件夹 |
|
if (![[NSFileManager defaultManager] fileExistsAtPath:productionFolderPath] && production_id != 0) { |
|
[[NSFileManager defaultManager] createDirectoryAtPath:productionFolderPath withIntermediateDirectories:YES attributes:nil error:nil]; |
|
} |
|
|
|
return productionFolderPath; |
|
} |
|
|
|
// 下载章节文件夹 |
|
- (NSString *)getDownloadChapterFolderPathWithProduction_id:(NSInteger)production_id chapter_id:(NSInteger)chapter_id productionType:(TFProductionType)productionType |
|
{ |
|
NSString *chapterFolderPath = [[self getDownloadProductionFolderPathWithProduction_id:production_id productionType:productionType] stringByAppendingPathComponent:[TFUtilsHelper stringToMD5:[NSString stringWithFormat:@"%@%@%@", [TFUtilsHelper formatStringWithInteger:productionType], [TFUtilsHelper formatStringWithInteger:production_id], [TFUtilsHelper formatStringWithInteger:chapter_id]]]]; |
|
|
|
// 创建章节文件夹 |
|
if (![[NSFileManager defaultManager] fileExistsAtPath:chapterFolderPath] && production_id != 0) { |
|
[[NSFileManager defaultManager] createDirectoryAtPath:chapterFolderPath withIntermediateDirectories:YES attributes:nil error:nil]; |
|
} |
|
|
|
return chapterFolderPath; |
|
} |
|
|
|
// 下载作品记录文件路径 |
|
- (NSString *)getDownloadProductionRecordPlistFilePathWithProductionType:(TFProductionType)productionType |
|
{ |
|
NSString *productionRecordFilePath = [[self getDownloadRootFolderPathWithProductionType:productionType] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.plist", [TFUtilsHelper stringToMD5:@"WXYZ_DownloadProductionRecordFile"]]]; |
|
|
|
if (![[NSFileManager defaultManager] fileExistsAtPath:productionRecordFilePath]) { |
|
[@[] writeToFile:productionRecordFilePath atomically:NO]; |
|
} |
|
|
|
return productionRecordFilePath; |
|
} |
|
|
|
// 下载章节记录文件路径 |
|
- (NSString *)getDownloadChapterRecordPlistFilePathWithProduction_id:(NSInteger)production_id productionType:(TFProductionType)productionType |
|
{ |
|
// 记录下载状态plist文件地址 |
|
NSString *chapterRecordFilePath = [[self getDownloadProductionFolderPathWithProduction_id:production_id productionType:productionType] stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.plist", [TFUtilsHelper stringToMD5:@"WXYZ_DownloadChapterRecordFile"]]]; |
|
|
|
if (![[NSFileManager defaultManager] fileExistsAtPath:chapterRecordFilePath]) { |
|
[@{} writeToFile:chapterRecordFilePath atomically:NO]; |
|
} |
|
|
|
return chapterRecordFilePath; |
|
} |
|
|
|
// 作品记录缓存变量 |
|
static NSMutableDictionary *_productionsRecordDictionary; |
|
- (NSMutableArray *)productionRecordDownloadArrayWithProductionType:(TFProductionType)productionType; |
|
{ |
|
if (!_productionsRecordDictionary) { |
|
// 此全局临时变量的作用是记录不同作品的下载记录,减少了文件的读写,增加访问效率 |
|
_productionsRecordDictionary = [NSMutableDictionary dictionary]; |
|
} |
|
|
|
NSMutableArray *t_arr = [_productionsRecordDictionary objectForKey:[NSString stringWithFormat:@"%@", [TFUtilsHelper formatStringWithInteger:productionType]]]; |
|
if (!t_arr) { |
|
|
|
NSMutableArray *localArr = [NSMutableArray arrayWithContentsOfFile:[self getDownloadProductionRecordPlistFilePathWithProductionType:productionType]]; |
|
|
|
t_arr = [NSMutableArray array]; |
|
|
|
for (NSString *json in localArr) { |
|
[t_arr addObject:[TFProductionModel modelWithJSON:json]]; |
|
} |
|
|
|
[_productionsRecordDictionary setObject:t_arr forKey:[NSString stringWithFormat:@"%@", [TFUtilsHelper formatStringWithInteger:productionType]]]; |
|
} |
|
|
|
return t_arr; |
|
} |
|
|
|
// 写入作品记录文件 |
|
- (BOOL)writeToPlistFileWithProductionType:(TFProductionType)productionType; |
|
{ |
|
NSMutableArray *t_downloadArr = [self productionRecordDownloadArrayWithProductionType:productionType]; |
|
|
|
NSMutableArray *saveArr = [NSMutableArray array]; |
|
|
|
for (TFProductionModel *t_model in t_downloadArr) { |
|
[saveArr addObject:[t_model modelToJSONString]]; |
|
} |
|
|
|
// 写入文件 |
|
if (![saveArr writeToFile:[self getDownloadProductionRecordPlistFilePathWithProductionType:productionType] atomically:NO]) { |
|
return NO; |
|
} |
|
return YES; |
|
} |
|
|
|
// 章节记录缓存变量 |
|
static NSMutableDictionary *_chaptersRecordDictionary; |
|
- (NSMutableDictionary *)chaptersRecordDownloadDictionaryWithProduction_id:(NSInteger)production_id productionType:(TFProductionType)productionType modelClass:(Class)modelClass |
|
{ |
|
if (!_chaptersRecordDictionary) { |
|
// 此全局临时变量的作用是记录不同作品的下载记录,减少了文件的读写,增加访问效率 |
|
_chaptersRecordDictionary = [NSMutableDictionary dictionary]; |
|
} |
|
|
|
NSMutableDictionary *t_dic = [_chaptersRecordDictionary objectForKey:[NSString stringWithFormat:@"%@", [TFUtilsHelper formatStringWithInteger:production_id]]]; |
|
if (!t_dic || t_dic.count == 0) { |
|
|
|
NSMutableDictionary *localDic = [NSMutableDictionary dictionaryWithContentsOfFile:[self getDownloadChapterRecordPlistFilePathWithProduction_id:production_id productionType:productionType]]; |
|
|
|
t_dic = [NSMutableDictionary dictionary]; |
|
for (NSString *key in localDic.allKeys) { |
|
id value = [localDic objectForKey:key]; |
|
if ([value isKindOfClass:[NSDictionary class]]) { |
|
[t_dic setObject:value forKey:key]; |
|
} else if ([value isEqualToString:identify_fail]) { |
|
[t_dic setObject:value forKey:key]; |
|
} else if (![value isEqual:identify_downloading] && value) { |
|
[t_dic setObject:[modelClass modelWithJSON:value] forKey:key]; |
|
} |
|
} |
|
|
|
[_chaptersRecordDictionary setObject:t_dic forKey:[NSString stringWithFormat:@"%@", [TFUtilsHelper formatStringWithInteger:production_id]]]; |
|
} |
|
|
|
return t_dic; |
|
} |
|
|
|
// 写入章节记录文件 |
|
- (BOOL)writeToChapterPlistFileWithProduction_id:(NSInteger)production_id productionType:(TFProductionType)productionType modelClass:(Class)modelClass |
|
{ |
|
NSMutableDictionary *t_downloadDic = [self chaptersRecordDownloadDictionaryWithProduction_id:production_id productionType:productionType modelClass:modelClass]; |
|
if (t_downloadDic.count == 0) { |
|
return NO; |
|
} |
|
|
|
NSMutableDictionary *save_dic = [NSMutableDictionary dictionary]; |
|
for (NSString *key in t_downloadDic.allKeys) { |
|
|
|
id value = [t_downloadDic objectForKey:key]; |
|
|
|
if ([value isKindOfClass:[modelClass class]]) { |
|
value = [value modelToJSONString]; |
|
} |
|
[save_dic setObject:value forKey:key]; |
|
} |
|
|
|
// 写入文件 |
|
if (![save_dic writeToFile:[self getDownloadChapterRecordPlistFilePathWithProduction_id:production_id productionType:productionType] atomically:NO]) { |
|
return NO; |
|
} |
|
return YES; |
|
} |
|
|
|
@end
|
|
|