|
@@ -0,0 +1,191 @@
|
|
|
+//
|
|
|
+// mixDownloadQueue.m
|
|
|
+// 双子星云手机
|
|
|
+//
|
|
|
+// Created by xd h on 2024/6/27.
|
|
|
+//
|
|
|
+
|
|
|
+#import "mixDownloadQueue.h"
|
|
|
+#import "mixDownloadManager.h"
|
|
|
+#import "mixDownloadCacheManager.h"
|
|
|
+#import "mixDownloadSession.h"
|
|
|
+#import "NSURLSession+mixDownloadTask.h"
|
|
|
+
|
|
|
+@interface mixDownloadQueue ()
|
|
|
+// 列队管理集合
|
|
|
+@property (nonatomic,strong) NSMutableArray <mixDownloadOperation *> *operations;
|
|
|
+
|
|
|
+@end
|
|
|
+
|
|
|
+@implementation mixDownloadQueue
|
|
|
+
|
|
|
+- (instancetype)init {
|
|
|
+
|
|
|
+ if (self = [super init]) {
|
|
|
+ _maxCount = 3;
|
|
|
+
|
|
|
+ }
|
|
|
+ return self;
|
|
|
+}
|
|
|
+
|
|
|
+- (NSMutableArray *)getOperationDoing {
|
|
|
+
|
|
|
+ NSMutableArray *doingArray = [NSMutableArray array];
|
|
|
+ for (mixDownloadOperation *operation in self.operations) {
|
|
|
+ if (operation.downloadState == DownloadStateDoing) {
|
|
|
+ [doingArray addObject:operation];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return doingArray;
|
|
|
+}
|
|
|
+
|
|
|
+#pragma mark - handle Out operations
|
|
|
+- (void)addDownloadWithSession:(NSURLSession *)session URL:(NSURL *)url begin:(void(^)(NSString *))begin progress:(void(^)(NSInteger,NSInteger))progress complete:(void(^)(NSDictionary *,NSError *))complet {
|
|
|
+ // 获取operation对象
|
|
|
+ mixDownloadOperation *operation = [self operationWithUrl:url.absoluteString];
|
|
|
+
|
|
|
+ if (operation == nil) { // 之前不存在此任务
|
|
|
+
|
|
|
+ operation = [[mixDownloadOperation alloc] initWith:url.absoluteString session:session];
|
|
|
+
|
|
|
+ if (operation == nil) {
|
|
|
+ // 没有下载任务代表已下载完成
|
|
|
+ NSDictionary *fileInfo = [mixDownloadCacheManager queryFileInfoWithUrl:url.absoluteString];
|
|
|
+ if (fileInfo && complet) {
|
|
|
+ complet(fileInfo,nil);
|
|
|
+ }else {
|
|
|
+ complet(nil,[NSError errorWithDomain:@"构建下载任务失败" code:-1 userInfo:nil]);
|
|
|
+ }
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ [self.operations addObject:operation];
|
|
|
+ }
|
|
|
+
|
|
|
+ if ([self getOperationDoing].count < self.maxCount) { // 下载中任务数少于最大任务限制
|
|
|
+ [operation.dataTask resume];
|
|
|
+ [self operationStartWithOperation:operation];
|
|
|
+ }else { // 下载中任务数大于最大任务限制
|
|
|
+// [operation.dataTask suspend];
|
|
|
+ [self operationWaitingWithOperation:operation];
|
|
|
+ HLog(@"下载中任务数等于最大任务限制:%zd",[self getOperationDoing].count);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+- (void)startAllTasksWithSession:(NSURLSession *)session {
|
|
|
+
|
|
|
+ // 开始所有的任务
|
|
|
+ [self.operations enumerateObjectsUsingBlock:^(mixDownloadOperation * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
|
|
|
+
|
|
|
+ mixDownloadOperation *operation = (mixDownloadOperation *)obj;
|
|
|
+ if (!operation.dataTask) { // 给plist里的任务添加dataTask 添加到operations
|
|
|
+ operation.dataTask = [self.session mix_downloadDataTaskWithURLString:operation.url startSize:operation.currentSize];
|
|
|
+ }
|
|
|
+
|
|
|
+ if ([self getOperationDoing].count < self.maxCount) { // 下载中任务数少于最大任务限制
|
|
|
+
|
|
|
+ switch (operation.dataTask.state) {
|
|
|
+ case NSURLSessionTaskStateRunning:
|
|
|
+ HLog(@"NSURLSessionTaskStateRunning");
|
|
|
+ break;
|
|
|
+
|
|
|
+ case NSURLSessionTaskStateSuspended:
|
|
|
+ HLog(@"NSURLSessionTaskStateSuspended");
|
|
|
+ break;
|
|
|
+
|
|
|
+ case NSURLSessionTaskStateCanceling:
|
|
|
+ HLog(@"NSURLSessionTaskStateCanceling");
|
|
|
+ operation.dataTask = [self.session mix_downloadDataTaskWithURLString:operation.url startSize:operation.currentSize];
|
|
|
+ break;
|
|
|
+
|
|
|
+ case NSURLSessionTaskStateCompleted:
|
|
|
+ HLog(@"NSURLSessionTaskStateCompleted");
|
|
|
+ break;
|
|
|
+
|
|
|
+ default:
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ [operation.dataTask resume]; // 开始
|
|
|
+ [self operationStartWithOperation:operation];
|
|
|
+ }else { // 下载中任务数大于最大任务限制
|
|
|
+// [operation.dataTask suspend];
|
|
|
+ [self operationWaitingWithOperation:operation];
|
|
|
+ HLog(@"下载中任务数等于最大任务限制:%zd",[self getOperationDoing].count);
|
|
|
+ }
|
|
|
+
|
|
|
+ }];
|
|
|
+}
|
|
|
+
|
|
|
+// 重启某一个operation 保存本地 通知外界
|
|
|
+- (void)operationStartWithOperation:(mixDownloadOperation *)operation {
|
|
|
+ operation.downloadState = DownloadStateDoing;
|
|
|
+ [mixDownloadCacheManager saveFileInfoWithDict:[operation downLoadInfoWithFinished:NO]];
|
|
|
+
|
|
|
+ //[[NSNotificationCenter defaultCenter] postNotificationName:SGDownloadTaskExeing object:nil userInfo:@{@"operation" : operation}];
|
|
|
+}
|
|
|
+
|
|
|
+// 等待某一个operation 保存本地 通知外界
|
|
|
+- (void)operationWaitingWithOperation:(mixDownloadOperation *)operation {
|
|
|
+ operation.downloadState = DownloadStateWaiting;
|
|
|
+ [mixDownloadCacheManager saveFileInfoWithDict:[operation downLoadInfoWithFinished:NO]];
|
|
|
+
|
|
|
+ //[[NSNotificationCenter defaultCenter] postNotificationName:SGDownloadTaskExeSuspend object:nil userInfo:@{@"operation" : operation}];
|
|
|
+}
|
|
|
+
|
|
|
+#pragma mark - query operation
|
|
|
+- (mixDownloadOperation *)operationWithUrl:(NSString *)url{
|
|
|
+ __block mixDownloadOperation *operation = nil;
|
|
|
+
|
|
|
+ [self.operations enumerateObjectsUsingBlock:^(mixDownloadOperation * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
|
|
|
+ if ([obj.url isEqualToString:url]) {
|
|
|
+ operation = obj;
|
|
|
+ *stop = YES;
|
|
|
+ }
|
|
|
+ }];
|
|
|
+
|
|
|
+ return operation;
|
|
|
+}
|
|
|
+
|
|
|
+#pragma mark - lazy load
|
|
|
+- (NSMutableArray<mixDownloadOperation *> *)operations {
|
|
|
+
|
|
|
+ if (!_operations) {
|
|
|
+ _operations = [NSMutableArray array];
|
|
|
+ [self addOperationsFromPlist];
|
|
|
+ }
|
|
|
+ return _operations;
|
|
|
+}
|
|
|
+
|
|
|
+- (void)addOperationsFromPlist {
|
|
|
+
|
|
|
+ [self.operations removeAllObjects];
|
|
|
+
|
|
|
+ NSMutableArray *operations = [[mixDownloadManager shareManager] getAllOperation];
|
|
|
+ for (mixDownloadOperation *operationPlist in operations) {
|
|
|
+
|
|
|
+ // 1、任务列表里取任务
|
|
|
+ mixDownloadOperation *operation = [self operationWithUrl:operationPlist.url];
|
|
|
+
|
|
|
+ // 2、本地plist文件里提取的任务
|
|
|
+ if (!operation) {
|
|
|
+ NSDictionary *dict = [mixDownloadCacheManager queryFileInfoWithUrl:operationPlist.url];
|
|
|
+ operation = [mixDownloadOperation mj_objectWithKeyValues:dict];
|
|
|
+ }
|
|
|
+
|
|
|
+ // 3、本地plist文件里提取的任务不存在dataTask
|
|
|
+ if(operation){
|
|
|
+ if (!operation.dataTask) {
|
|
|
+ operation.dataTask = [self.session mix_downloadDataTaskWithURLString:operation.url startSize:operation.currentSize];
|
|
|
+ operation.handle = [NSFileHandle fileHandleForWritingAtPath:operation.fullPath];
|
|
|
+
|
|
|
+ [self.operations addObject:operation];
|
|
|
+ }
|
|
|
+ }
|
|
|
+ else{
|
|
|
+ HLog(@"%@ --- 没找到",operationPlist.url)
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+@end
|