TYDownLoadDataManager.m 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612
  1. //
  2. // TYDownLoadDataManager.m
  3. // TYDownloadManagerDemo
  4. //
  5. // Created by tany on 16/6/12.
  6. // Copyright © 2016年 tany. All rights reserved.
  7. //
  8. #import "TYDownLoadDataManager.h"
  9. /**
  10. * 下载模型
  11. */
  12. @interface TYDownloadModel ()
  13. // >>>>>>>>>>>>>>>>>>>>>>>>>> task info
  14. // 下载状态
  15. @property (nonatomic, assign) TYDownloadState state;
  16. // 下载任务
  17. @property (nonatomic, strong) NSURLSessionDataTask *task;
  18. // 文件流
  19. @property (nonatomic, strong) NSOutputStream *stream;
  20. // 下载文件路径
  21. @property (nonatomic, strong) NSString *filePath;
  22. // 下载时间
  23. @property (nonatomic, strong) NSDate *downloadDate;
  24. // 手动取消当做暂停
  25. @property (nonatomic, assign) BOOL manualCancle;
  26. @end
  27. /**
  28. * 下载进度
  29. */
  30. @interface TYDownloadProgress ()
  31. // 续传大小
  32. @property (nonatomic, assign) int64_t resumeBytesWritten;
  33. // 这次写入的数量
  34. @property (nonatomic, assign) int64_t bytesWritten;
  35. // 已下载的数量
  36. @property (nonatomic, assign) int64_t totalBytesWritten;
  37. // 文件的总大小
  38. @property (nonatomic, assign) int64_t totalBytesExpectedToWrite;
  39. // 下载进度
  40. @property (nonatomic, assign) float progress;
  41. // 下载速度
  42. @property (nonatomic, assign) float speed;
  43. // 下载剩余时间
  44. @property (nonatomic, assign) int remainingTime;
  45. @end
  46. @interface TYDownLoadDataManager ()
  47. // >>>>>>>>>>>>>>>>>>>>>>>>>> file info
  48. // 文件管理
  49. @property (nonatomic, strong) NSFileManager *fileManager;
  50. // 缓存文件目录
  51. @property (nonatomic, strong) NSString *downloadDirectory;
  52. // >>>>>>>>>>>>>>>>>>>>>>>>>> session info
  53. // 下载seesion会话
  54. @property (nonatomic, strong) NSURLSession *session;
  55. // 下载模型字典 key = url
  56. @property (nonatomic, strong) NSMutableDictionary *downloadingModelDic;
  57. // 下载中的模型
  58. @property (nonatomic, strong) NSMutableArray *waitingDownloadModels;
  59. // 等待中的模型
  60. @property (nonatomic, strong) NSMutableArray *downloadingModels;
  61. // 回调代理的队列
  62. @property (strong, nonatomic) NSOperationQueue *queue;
  63. @end
  64. @implementation TYDownLoadDataManager
  65. #pragma mark - getter
  66. + (TYDownLoadDataManager *)manager
  67. {
  68. static id sharedInstance = nil;
  69. static dispatch_once_t onceToken;
  70. dispatch_once(&onceToken, ^{
  71. sharedInstance = [[self alloc] init];
  72. });
  73. return sharedInstance;
  74. }
  75. - (instancetype)init
  76. {
  77. if (self = [super init]) {
  78. _maxDownloadCount = 1;
  79. _resumeDownloadFIFO = YES;
  80. _isBatchDownload = NO;
  81. }
  82. return self;
  83. }
  84. - (NSFileManager *)fileManager
  85. {
  86. if (!_fileManager) {
  87. _fileManager = [[NSFileManager alloc]init];
  88. }
  89. return _fileManager;
  90. }
  91. - (NSURLSession *)session
  92. {
  93. if (!_session) {
  94. _session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:self.queue];
  95. }
  96. return _session;
  97. }
  98. - (NSOperationQueue *)queue
  99. {
  100. if (!_queue) {
  101. _queue = [[NSOperationQueue alloc]init];
  102. _queue.maxConcurrentOperationCount = 1;
  103. }
  104. return _queue;
  105. }
  106. - (NSString *)downloadDirectory
  107. {
  108. if (!_downloadDirectory) {
  109. _downloadDirectory = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"TYDownloadCache"];
  110. [self createDirectory:_downloadDirectory];
  111. }
  112. return _downloadDirectory;
  113. }
  114. // 下载文件信息plist路径
  115. - (NSString *)fileSizePathWithDownloadModel:(TYDownloadModel *)downloadModel
  116. {
  117. return [downloadModel.downloadDirectory stringByAppendingPathComponent:@"downloadsFileSize.plist"];
  118. }
  119. // 下载model字典
  120. - (NSMutableDictionary *)downloadingModelDic
  121. {
  122. if (!_downloadingModelDic) {
  123. _downloadingModelDic = [NSMutableDictionary dictionary];
  124. }
  125. return _downloadingModelDic;
  126. }
  127. // 等待下载model队列
  128. - (NSMutableArray *)waitingDownloadModels
  129. {
  130. if (!_waitingDownloadModels) {
  131. _waitingDownloadModels = [NSMutableArray array];
  132. }
  133. return _waitingDownloadModels;
  134. }
  135. // 正在下载model队列
  136. - (NSMutableArray *)downloadingModels
  137. {
  138. if (!_downloadingModels) {
  139. _downloadingModels = [NSMutableArray array];
  140. }
  141. return _downloadingModels;
  142. }
  143. #pragma mark - downlaod
  144. // 开始下载
  145. - (TYDownloadModel *)startDownloadURLString:(NSString *)URLString toDestinationPath:(NSString *)destinationPath progress:(TYDownloadProgressBlock)progress state:(TYDownloadStateBlock)state
  146. {
  147. // 验证下载地址
  148. if (!URLString) {
  149. NSLog(@"dwonloadURL can't nil");
  150. return nil;
  151. }
  152. TYDownloadModel *downloadModel = [self downLoadingModelForURLString:URLString];
  153. if (!downloadModel || ![downloadModel.filePath isEqualToString:destinationPath]) {
  154. downloadModel = [[TYDownloadModel alloc]initWithURLString:URLString filePath:destinationPath];
  155. }
  156. [self startWithDownloadModel:downloadModel progress:progress state:state];
  157. return downloadModel;
  158. }
  159. - (void)startWithDownloadModel:(TYDownloadModel *)downloadModel progress:(TYDownloadProgressBlock)progress state:(TYDownloadStateBlock)state
  160. {
  161. downloadModel.progressBlock = progress;
  162. downloadModel.stateBlock = state;
  163. [self startWithDownloadModel:downloadModel];
  164. }
  165. - (void)startWithDownloadModel:(TYDownloadModel *)downloadModel
  166. {
  167. if (!downloadModel) {
  168. return;
  169. }
  170. if (downloadModel.state == TYDownloadStateReadying) {
  171. [self downloadModel:downloadModel didChangeState:TYDownloadStateReadying filePath:nil error:nil];
  172. return;
  173. }
  174. // 验证是否已经下载文件
  175. if ([self isDownloadCompletedWithDownloadModel:downloadModel]) {
  176. downloadModel.state = TYDownloadStateCompleted;
  177. [self downloadModel:downloadModel didChangeState:TYDownloadStateCompleted filePath:downloadModel.filePath error:nil];
  178. return;
  179. }
  180. // 验证是否存在
  181. if (downloadModel.task && downloadModel.task.state == NSURLSessionTaskStateRunning) {
  182. downloadModel.state = TYDownloadStateRunning;
  183. [self downloadModel:downloadModel didChangeState:TYDownloadStateRunning filePath:nil error:nil];
  184. return;
  185. }
  186. [self resumeWithDownloadModel:downloadModel];
  187. }
  188. // 自动下载下一个等待队列任务
  189. - (void)willResumeNextWithDowloadModel:(TYDownloadModel *)downloadModel
  190. {
  191. if (_isBatchDownload) {
  192. return;
  193. }
  194. @synchronized (self) {
  195. [self.downloadingModels removeObject:downloadModel];
  196. // 还有未下载的
  197. if (self.waitingDownloadModels.count > 0) {
  198. [self resumeWithDownloadModel:_resumeDownloadFIFO ? self.waitingDownloadModels.firstObject:self.waitingDownloadModels.lastObject];
  199. }
  200. }
  201. }
  202. // 是否开启下载等待队列任务
  203. - (BOOL)canResumeDownlaodModel:(TYDownloadModel *)downloadModel
  204. {
  205. if (_isBatchDownload) {
  206. return YES;
  207. }
  208. @synchronized (self) {
  209. if (self.downloadingModels.count >= _maxDownloadCount ) {
  210. if ([self.waitingDownloadModels indexOfObject:downloadModel] == NSNotFound) {
  211. [self.waitingDownloadModels addObject:downloadModel];
  212. self.downloadingModelDic[downloadModel.downloadURL] = downloadModel;
  213. }
  214. downloadModel.state = TYDownloadStateReadying;
  215. [self downloadModel:downloadModel didChangeState:TYDownloadStateReadying filePath:nil error:nil];
  216. return NO;
  217. }
  218. if ([self.waitingDownloadModels indexOfObject:downloadModel] != NSNotFound) {
  219. [self.waitingDownloadModels removeObject:downloadModel];
  220. }
  221. if ([self.downloadingModels indexOfObject:downloadModel] == NSNotFound) {
  222. [self.downloadingModels addObject:downloadModel];
  223. }
  224. return YES;
  225. }
  226. }
  227. // 恢复下载
  228. - (void)resumeWithDownloadModel:(TYDownloadModel *)downloadModel
  229. {
  230. if (!downloadModel) {
  231. return;
  232. }
  233. if (![self canResumeDownlaodModel:downloadModel]) {
  234. return;
  235. }
  236. // 如果task 不存在 或者 取消了
  237. if (!downloadModel.task || downloadModel.task.state == NSURLSessionTaskStateCanceling) {
  238. NSString *URLString = downloadModel.downloadURL;
  239. // 创建请求
  240. NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:URLString]];
  241. // 设置请求头
  242. NSString *range = [NSString stringWithFormat:@"bytes=%zd-", [self fileSizeWithDownloadModel:downloadModel]];
  243. [request setValue:range forHTTPHeaderField:@"Range"];
  244. // 创建流
  245. downloadModel.stream = [NSOutputStream outputStreamToFileAtPath:downloadModel.filePath append:YES];
  246. downloadModel.downloadDate = [NSDate date];
  247. self.downloadingModelDic[downloadModel.downloadURL] = downloadModel;
  248. // 创建一个Data任务
  249. downloadModel.task = [self.session dataTaskWithRequest:request];
  250. downloadModel.task.taskDescription = URLString;
  251. }
  252. [downloadModel.task resume];
  253. downloadModel.state = TYDownloadStateRunning;
  254. [self downloadModel:downloadModel didChangeState:TYDownloadStateRunning filePath:nil error:nil];
  255. }
  256. // 暂停下载
  257. - (void)suspendWithDownloadModel:(TYDownloadModel *)downloadModel
  258. {
  259. if (!downloadModel.manualCancle) {
  260. downloadModel.manualCancle = YES;
  261. [downloadModel.task cancel];
  262. }
  263. }
  264. // 取消下载
  265. - (void)cancleWithDownloadModel:(TYDownloadModel *)downloadModel
  266. {
  267. if (!downloadModel.task && downloadModel.state == TYDownloadStateReadying) {
  268. [self removeDownLoadingModelForURLString:downloadModel.downloadURL];
  269. @synchronized (self) {
  270. [self.waitingDownloadModels removeObject:downloadModel];
  271. }
  272. downloadModel.state = TYDownloadStateNone;
  273. [self downloadModel:downloadModel didChangeState:TYDownloadStateNone filePath:nil error:nil];
  274. return;
  275. }
  276. if (downloadModel.state != TYDownloadStateCompleted && downloadModel.state != TYDownloadStateFailed){
  277. [downloadModel.task cancel];
  278. }
  279. }
  280. #pragma mark - delete file
  281. - (void)deleteFileWithDownloadModel:(TYDownloadModel *)downloadModel
  282. {
  283. if (!downloadModel || !downloadModel.filePath) {
  284. return;
  285. }
  286. // 文件是否存在
  287. if ([self.fileManager fileExistsAtPath:downloadModel.filePath]) {
  288. // 删除任务
  289. downloadModel.task.taskDescription = nil;
  290. [downloadModel.task cancel];
  291. downloadModel.task = nil;
  292. // 删除流
  293. if (downloadModel.stream.streamStatus > NSStreamStatusNotOpen && downloadModel.stream.streamStatus < NSStreamStatusClosed) {
  294. [downloadModel.stream close];
  295. }
  296. downloadModel.stream = nil;
  297. // 删除沙盒中的资源
  298. NSError *error = nil;
  299. [self.fileManager removeItemAtPath:downloadModel.filePath error:&error];
  300. if (error) {
  301. NSLog(@"delete file error %@",error);
  302. }
  303. [self removeDownLoadingModelForURLString:downloadModel.downloadURL];
  304. // 删除资源总长度
  305. if ([self.fileManager fileExistsAtPath:[self fileSizePathWithDownloadModel:downloadModel]]) {
  306. @synchronized (self) {
  307. NSMutableDictionary *dict = [self fileSizePlistWithDownloadModel:downloadModel];
  308. [dict removeObjectForKey:downloadModel.downloadURL];
  309. [dict writeToFile:[self fileSizePathWithDownloadModel:downloadModel] atomically:YES];
  310. }
  311. }
  312. }
  313. }
  314. - (void)deleteAllFileWithDownloadDirectory:(NSString *)downloadDirectory
  315. {
  316. if (!downloadDirectory) {
  317. downloadDirectory = self.downloadDirectory;
  318. }
  319. if ([self.fileManager fileExistsAtPath:downloadDirectory]) {
  320. // 删除任务
  321. for (TYDownloadModel *downloadModel in [self.downloadingModelDic allValues]) {
  322. if ([downloadModel.downloadDirectory isEqualToString:downloadDirectory]) {
  323. // 删除任务
  324. downloadModel.task.taskDescription = nil;
  325. [downloadModel.task cancel];
  326. downloadModel.task = nil;
  327. // 删除流
  328. if (downloadModel.stream.streamStatus > NSStreamStatusNotOpen && downloadModel.stream.streamStatus < NSStreamStatusClosed) {
  329. [downloadModel.stream close];
  330. }
  331. downloadModel.stream = nil;
  332. }
  333. }
  334. // 删除沙盒中所有资源
  335. [self.fileManager removeItemAtPath:downloadDirectory error:nil];
  336. }
  337. }
  338. #pragma mark - public
  339. // 获取下载模型
  340. - (TYDownloadModel *)downLoadingModelForURLString:(NSString *)URLString
  341. {
  342. return [self.downloadingModelDic objectForKey:URLString];
  343. }
  344. // 是否已经下载
  345. - (BOOL)isDownloadCompletedWithDownloadModel:(TYDownloadModel *)downloadModel
  346. {
  347. long long fileSize = [self fileSizeInCachePlistWithDownloadModel:downloadModel];
  348. if (fileSize > 0 && fileSize == [self fileSizeWithDownloadModel:downloadModel]) {
  349. return YES;
  350. }
  351. return NO;
  352. }
  353. // 当前下载进度
  354. - (TYDownloadProgress *)progessWithDownloadModel:(TYDownloadModel *)downloadModel
  355. {
  356. TYDownloadProgress *progress = [[TYDownloadProgress alloc]init];
  357. progress.totalBytesExpectedToWrite = [self fileSizeInCachePlistWithDownloadModel:downloadModel];
  358. progress.totalBytesWritten = MIN([self fileSizeWithDownloadModel:downloadModel], progress.totalBytesExpectedToWrite);
  359. progress.progress = progress.totalBytesExpectedToWrite > 0 ? 1.0*progress.totalBytesWritten/progress.totalBytesExpectedToWrite : 0;
  360. return progress;
  361. }
  362. #pragma mark - private
  363. - (void)downloadModel:(TYDownloadModel *)downloadModel didChangeState:(TYDownloadState)state filePath:(NSString *)filePath error:(NSError *)error
  364. {
  365. if (_delegate && [_delegate respondsToSelector:@selector(downloadModel:didChangeState:filePath:error:)]) {
  366. [_delegate downloadModel:downloadModel didChangeState:state filePath:filePath error:error];
  367. }
  368. if (downloadModel.stateBlock) {
  369. downloadModel.stateBlock(state,filePath,error);
  370. }
  371. }
  372. - (void)downloadModel:(TYDownloadModel *)downloadModel updateProgress:(TYDownloadProgress *)progress
  373. {
  374. if (_delegate && [_delegate respondsToSelector:@selector(downloadModel:didUpdateProgress:)]) {
  375. [_delegate downloadModel:downloadModel didUpdateProgress:progress];
  376. }
  377. if (downloadModel.progressBlock) {
  378. downloadModel.progressBlock(progress);
  379. }
  380. }
  381. // 创建缓存目录文件
  382. - (void)createDirectory:(NSString *)directory
  383. {
  384. if (![self.fileManager fileExistsAtPath:directory]) {
  385. [self.fileManager createDirectoryAtPath:directory withIntermediateDirectories:YES attributes:nil error:NULL];
  386. }
  387. }
  388. // 获取文件大小
  389. - (long long)fileSizeWithDownloadModel:(TYDownloadModel *)downloadModel{
  390. NSString *filePath = downloadModel.filePath;
  391. if (![self.fileManager fileExistsAtPath:filePath]) return 0;
  392. return [[self.fileManager attributesOfItemAtPath:filePath error:nil] fileSize];
  393. }
  394. // 获取plist保存文件大小
  395. - (long long)fileSizeInCachePlistWithDownloadModel:(TYDownloadModel *)downloadModel
  396. {
  397. NSDictionary *downloadsFileSizePlist = [NSDictionary dictionaryWithContentsOfFile:[self fileSizePathWithDownloadModel:downloadModel]];
  398. return [downloadsFileSizePlist[downloadModel.downloadURL] longLongValue];
  399. }
  400. // 获取plist文件内容
  401. - (NSMutableDictionary *)fileSizePlistWithDownloadModel:(TYDownloadModel *)downloadModel
  402. {
  403. NSMutableDictionary *downloadsFileSizePlist = [NSMutableDictionary dictionaryWithContentsOfFile:[self fileSizePathWithDownloadModel:downloadModel]];
  404. if (!downloadsFileSizePlist) {
  405. downloadsFileSizePlist = [NSMutableDictionary dictionary];
  406. }
  407. return downloadsFileSizePlist;
  408. }
  409. - (void)removeDownLoadingModelForURLString:(NSString *)URLString
  410. {
  411. [self.downloadingModelDic removeObjectForKey:URLString];
  412. }
  413. #pragma mark - NSURLSessionDelegate
  414. /**
  415. * 接收到响应
  416. */
  417. - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSHTTPURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler
  418. {
  419. TYDownloadModel *downloadModel = [self downLoadingModelForURLString:dataTask.taskDescription];
  420. if (!downloadModel) {
  421. return;
  422. }
  423. // 创建目录
  424. [self createDirectory:_downloadDirectory];
  425. [self createDirectory:downloadModel.downloadDirectory];
  426. // 打开流
  427. [downloadModel.stream open];
  428. // 获得服务器这次请求 返回数据的总长度
  429. long long totalBytesWritten = [self fileSizeWithDownloadModel:downloadModel];
  430. long long totalBytesExpectedToWrite = totalBytesWritten + dataTask.countOfBytesExpectedToReceive;
  431. downloadModel.progress.resumeBytesWritten = totalBytesWritten;
  432. downloadModel.progress.totalBytesWritten = totalBytesWritten;
  433. downloadModel.progress.totalBytesExpectedToWrite = totalBytesExpectedToWrite;
  434. // 存储总长度
  435. @synchronized (self) {
  436. NSMutableDictionary *dic = [self fileSizePlistWithDownloadModel:downloadModel];
  437. dic[downloadModel.downloadURL] = @(totalBytesExpectedToWrite);
  438. [dic writeToFile:[self fileSizePathWithDownloadModel:downloadModel] atomically:YES];
  439. }
  440. // 接收这个请求,允许接收服务器的数据
  441. completionHandler(NSURLSessionResponseAllow);
  442. }
  443. /**
  444. * 接收到服务器返回的数据
  445. */
  446. - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
  447. {
  448. TYDownloadModel *downloadModel = [self downLoadingModelForURLString:dataTask.taskDescription];
  449. if (!downloadModel || downloadModel.state == TYDownloadStateSuspended) {
  450. return;
  451. }
  452. // 写入数据
  453. [downloadModel.stream write:data.bytes maxLength:data.length];
  454. // 下载进度
  455. downloadModel.progress.bytesWritten = data.length;
  456. downloadModel.progress.totalBytesWritten += downloadModel.progress.bytesWritten;
  457. downloadModel.progress.progress = MIN(1.0, 1.0*downloadModel.progress.totalBytesWritten/downloadModel.progress.totalBytesExpectedToWrite);
  458. // 时间
  459. NSTimeInterval downloadTime = -1 * [downloadModel.downloadDate timeIntervalSinceNow];
  460. downloadModel.progress.speed = (downloadModel.progress.totalBytesWritten - downloadModel.progress.resumeBytesWritten) / downloadTime;
  461. int64_t remainingContentLength = downloadModel.progress.totalBytesExpectedToWrite - downloadModel.progress.totalBytesWritten;
  462. downloadModel.progress.remainingTime = ceilf(remainingContentLength / downloadModel.progress.speed);
  463. dispatch_async(dispatch_get_main_queue(), ^(){
  464. [self downloadModel:downloadModel updateProgress:downloadModel.progress];
  465. });
  466. }
  467. /**
  468. * 请求完毕(成功|失败)
  469. */
  470. - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
  471. {
  472. TYDownloadModel *downloadModel = [self downLoadingModelForURLString:task.taskDescription];
  473. if (!downloadModel) {
  474. return;
  475. }
  476. // 关闭流
  477. [downloadModel.stream close];
  478. downloadModel.stream = nil;
  479. downloadModel.task = nil;
  480. [self removeDownLoadingModelForURLString:downloadModel.downloadURL];
  481. if (downloadModel.manualCancle) {
  482. // 暂停下载
  483. dispatch_async(dispatch_get_main_queue(), ^(){
  484. downloadModel.manualCancle = NO;
  485. downloadModel.state = TYDownloadStateSuspended;
  486. [self downloadModel:downloadModel didChangeState:TYDownloadStateSuspended filePath:nil error:nil];
  487. [self willResumeNextWithDowloadModel:downloadModel];
  488. });
  489. }else if (error){
  490. // 下载失败
  491. dispatch_async(dispatch_get_main_queue(), ^(){
  492. downloadModel.state = TYDownloadStateFailed;
  493. [self downloadModel:downloadModel didChangeState:TYDownloadStateFailed filePath:nil error:error];
  494. [self willResumeNextWithDowloadModel:downloadModel];
  495. });
  496. }else if ([self isDownloadCompletedWithDownloadModel:downloadModel]) {
  497. // 下载完成
  498. dispatch_async(dispatch_get_main_queue(), ^(){
  499. downloadModel.state = TYDownloadStateCompleted;
  500. [self downloadModel:downloadModel didChangeState:TYDownloadStateCompleted filePath:downloadModel.filePath error:nil];
  501. [self willResumeNextWithDowloadModel:downloadModel];
  502. });
  503. }else {
  504. // 下载完成
  505. dispatch_async(dispatch_get_main_queue(), ^(){
  506. downloadModel.state = TYDownloadStateCompleted;
  507. [self downloadModel:downloadModel didChangeState:TYDownloadStateCompleted filePath:downloadModel.filePath error:nil];
  508. [self willResumeNextWithDowloadModel:downloadModel];
  509. });
  510. }
  511. }
  512. @end