Explorar o código

1.下载一个文件完成

huangxiaodong hai 11 meses
pai
achega
1c98e49c67

+ 1 - 1
创维盒子/双子星云手机/Class/Set/uploadFile/mixDownloadManager/mixDownloadCacheManager.m

@@ -83,7 +83,7 @@ static dispatch_semaphore_t _semaphore;
 + (BOOL)saveFileInfoWithDict:(NSDictionary *)dict {
     
     // 多账号下载 判断是否需要缓存记录
-    HLog(@"增加配置信息:%@", dict);
+    //HLog(@"增加配置信息:%@", dict);
     if ([[dict allKeys] containsObject:@"fullPath"]) {
         NSArray *fileArray = [[dict objectForKey:@"fullPath"] pathComponents];
         NSString *filePathAccount = @"0";

+ 13 - 0
创维盒子/双子星云手机/Class/Set/uploadFile/mixDownloadManager/mixDownloadManager.h

@@ -12,6 +12,19 @@ NS_ASSUME_NONNULL_BEGIN
 
 #define KMixDownloadUID  [mixDownloadManager shareManager].uid
 
+/** 下载中通知 */
+#define  mixDownloadTaskExeing        @"mixDownloadTaskExeing"
+/** 下载失败通知 */
+#define  mixDownloadTaskExeError      @"mixDownloadTaskExeError"
+/** 下载完成通知 */
+#define  mixDownloadTaskExeEnd        @"mixDownloadTaskExeEnd"
+/** 下载暂停/等待中通知 */
+#define  mixDownloadTaskExeSuspend    @"mixDownloadTaskExeSuspend"
+/** 删除下载任务通知 */
+#define  mixDownloadTaskExeDelete     @"mixDownloadTaskExeDelete"
+/** 移除loading通知 */
+#define  SGDownloadRemoveLoading     @"mixDownloadRemoveLoading"
+
 /**
  block 回调
  */

+ 30 - 1
创维盒子/双子星云手机/Class/Set/uploadFile/mixDownloadManager/mixDownloadOperation.h

@@ -20,7 +20,36 @@ typedef  enum : NSUInteger {
 
 NS_ASSUME_NONNULL_BEGIN
 
-@interface mixDownloadOperation : NSObject
+typedef void(^mixReceiveResponseOperation)(NSString *filePath);
+typedef void(^mixReceivDataOperation)(NSInteger completeSize,NSInteger expectSize);
+typedef void(^mixCompleteOperation)(NSDictionary *respose,NSError *error);
+
+@protocol mixDownloadOperationProtocol <NSObject>
+                                    
+// 供queue管理方法
+
+// 处理响应值
+- (void)operateWithResponse:(NSURLResponse *)response;
+// 处理接收到的碎片
+- (void)operateWithReceivingData:(NSData *)data;
+// 处理完成回调
+- (void)operateWithComplete:(NSError *)error;
+
+
+/**
+ 设置block回调
+
+ @param didReceiveResponse 开始下载的回调
+ @param didReceivData 接收到下载的回调
+ @param didComplete 下载完成的回调
+ */
+- (void)configCallBacksWithDidReceiveResponse:(mixReceiveResponseOperation)didReceiveResponse
+                                didReceivData:(mixReceivDataOperation)didReceivData
+                                  didComplete:(mixCompleteOperation)didComplete;
+
+@end
+
+@interface mixDownloadOperation : NSObject <mixDownloadOperationProtocol>
 
 /** 绑定的标示及task的创建 */
 @property (readonly,nonatomic, copy)NSString *url;

+ 167 - 0
创维盒子/双子星云手机/Class/Set/uploadFile/mixDownloadManager/mixDownloadOperation.m

@@ -9,6 +9,16 @@
 #import "mixDownloadManager.h"
 #import "NSURLSession+mixDownloadTask.h"
 
+NSString * const mixDownloadCompleteNoti = @"mixDownloadCompleteNoti";
+
+@interface mixDownloadOperation ()
+{
+    mixReceiveResponseOperation  _didReceiveResponseCallBack;
+    mixReceivDataOperation       _didReceivDataCallBack;
+    mixCompleteOperation         _didCompleteCallBack;
+}
+@end
+
 @implementation mixDownloadOperation
 - (instancetype)initWith:(NSString *)url session:(NSURLSession *)session {
     
@@ -57,6 +67,163 @@
     return  [fileInfo[NSFileSize] longLongValue];
 }
 
+#pragma mark - mixDownloadOperationProtocol
+// 接收到相应时
+- (void)operateWithResponse:(NSURLResponse *)response {
+    // 总的size
+    if (self.currentSize + response.expectedContentLength == 0) {
+        HLog(@"下载数据回调异常");
+        return;
+    }
+    self.totalSize = self.currentSize + response.expectedContentLength;
+    
+    // 创建空的文件夹
+    if (self.currentSize == 0) {
+        // 创建空的文件
+        [[NSFileManager defaultManager]  createFileAtPath:self.fullPath contents:nil attributes:nil];
+    }
+    
+    // 创建文件句柄
+    self.handle = [NSFileHandle fileHandleForWritingAtPath:self.fullPath];
+    
+    // 文件句柄移动到文件末尾 位置 // 返回值是 unsign long long
+    [self.handle seekToEndOfFile];
+    
+    // 开始下载记录文件下载信息
+    _downloadState = DownloadStateDoing;
+    [mixDownloadCacheManager saveFileInfoWithDict:[self downLoadInfoWithFinished:NO]];
+    
+    // 回调给外界
+    if (_didReceiveResponseCallBack) {
+        dispatch_async(dispatch_get_main_queue(), ^{
+            self->_didReceiveResponseCallBack(self.fullPath);
+            
+        });
+        
+    }
+}
+
+- (void)operateWithReceivingData:(NSData *)data {
+    // 获得已经下载的文件大小
+    self.currentSize += data.length;
+    HLog(@"currentSize:%lld---progress:%.2f", self.currentSize, 1.00*self.currentSize/self.totalSize);
+    
+//    long long hhhh =  [self.handle seekToEndOfFile];
+//    HLog(@"hhhh:%lld---handle:%@", hhhh, self.handle);
+    
+    // 写入文件
+    [self.handle writeData:data];
+    
+    // 下载状态 通知代理
+    if (_didReceivDataCallBack) {
+        dispatch_async(dispatch_get_main_queue(), ^{
+            self->_didReceivDataCallBack((NSUInteger)self.currentSize,(NSUInteger)self.totalSize);
+            
+        });
+    }
+    
+    // 下载中通知
+    [self operationDoningWithOperation:self];
+}
+
+- (void)operateWithComplete:(NSError *)error {
+    // 关闭文件句柄
+    [self.handle closeFile];
+    // 释放文件句柄
+    self.handle = nil;
+    
+    // 完成下载 通知 block
+    if (error) {
+        [self completFailueWithError:error];
+    } else {
+        [self completCusesseWithCode:1];
+    }
+}
+
+- (void)configCallBacksWithDidReceiveResponse:(mixReceiveResponseOperation)didReceiveResponse
+                                didReceivData:(mixReceivDataOperation)didReceivData
+                                  didComplete:(mixCompleteOperation)didComplete {
+    _didReceiveResponseCallBack  = didReceiveResponse;
+    _didReceivDataCallBack       = didReceivData;
+    _didCompleteCallBack         = didComplete;
+    
+}
+
+#pragma mark - operations
+/** 成功回调 1代表下载后成功回调 2代表直接从磁盘中获取了 */
+- (void)completCusesseWithCode:(NSInteger)code {
+    // 获取下载信息
+    NSDictionary *dict = [self downLoadInfoWithFinished:YES];
+    
+    
+    // 通知
+    [[NSNotificationCenter defaultCenter] postNotificationName:mixDownloadCompleteNoti object:self userInfo:dict];
+    
+    if (code == 1) {
+        // 存储 文件下载信息
+        HLog(@"%zd", DownloadStateCompleted);
+        _downloadState = DownloadStateCompleted;
+        self.timeStamp = [iTools getNowTimeStamp];
+        [mixDownloadCacheManager saveFileInfoWithDict:dict];
+    }
+    
+    // 回到主线程 回调
+    if (_didCompleteCallBack) {
+        dispatch_async(dispatch_get_main_queue(), ^{
+            self->_didCompleteCallBack(dict,nil);
+        });
+    }
+    
+    // 成功通知
+    [self operationSuccessWithOperation:self];
+}
+
+/** 失败回调 */
+- (void)completFailueWithError:(NSError *)error {
+    
+    // 发通知
+    [[NSNotificationCenter defaultCenter] postNotificationName:mixDownloadCompleteNoti object:self userInfo:@{@"error":error}];
+    // 存储
+    _downloadState = DownloadStateFailed;
+    [mixDownloadCacheManager saveFileInfoWithDict:[self downLoadInfoWithFinished:NO]];
+    
+    // 回调
+    if (_didCompleteCallBack) {
+        dispatch_async(dispatch_get_main_queue(), ^{
+            self->_didCompleteCallBack(nil,error);
+        });
+    }
+    
+    // 失败通知
+    [self operationFailedWithOperation:self];
+}
+
+
+#pragma mark 发送通知
+// 失败某一个operation 保存本地 通知外界
+- (void)operationFailedWithOperation:(mixDownloadOperation *)operation {
+    HLog(@"SGDownloadTaskExeError");
+    operation.downloadState = DownloadStateFailed;
+    [mixDownloadCacheManager saveFileInfoWithDict:[operation downLoadInfoWithFinished:NO]];
+    [[NSNotificationCenter defaultCenter] postNotificationName:mixDownloadTaskExeError object:nil userInfo:@{@"operation" : operation}];
+}
+
+// 重启某一个operation 保存本地 通知外界
+- (void)operationDoningWithOperation:(mixDownloadOperation *)operation {
+    HLog(@"SGDownloadTaskExeing");
+//    operation.downloadState = DownloadStateDoing; // 暂停之后 数据回来 状态会被修改为下载中 不科学
+    [mixDownloadCacheManager saveFileInfoWithDict:[operation downLoadInfoWithFinished:NO]];
+    [[NSNotificationCenter defaultCenter] postNotificationName:mixDownloadTaskExeing object:nil userInfo:@{@"operation" : operation}];
+}
+
+// 等待某一个operation 保存本地 通知外界
+- (void)operationSuccessWithOperation:(mixDownloadOperation *)operation {
+    HLog(@"SGDownloadTaskExeEnd");
+    operation.downloadState = DownloadStateCompleted;
+    [mixDownloadCacheManager saveFileInfoWithDict:[operation downLoadInfoWithFinished:YES]];
+    [[NSNotificationCenter defaultCenter] postNotificationName:mixDownloadTaskExeEnd object:nil userInfo:@{@"operation" : operation}];
+}
+
 
 #pragma mark - get download info
 // 构造回调信息

+ 8 - 0
创维盒子/双子星云手机/Class/Set/uploadFile/mixDownloadManager/mixDownloadQueue.h

@@ -24,6 +24,14 @@ NS_ASSUME_NONNULL_BEGIN
                    complete:(void(^)(NSDictionary *respose,NSError *error))complet;
 
 - (void)startAllTasksWithSession:(NSURLSession *)session;
+
+// 供downloader 处理下载调用
+- (void)dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response;
+
+- (void)dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data;
+
+- (void)task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error;
+
 @end
 
 NS_ASSUME_NONNULL_END

+ 28 - 0
创维盒子/双子星云手机/Class/Set/uploadFile/mixDownloadManager/mixDownloadQueue.m

@@ -134,6 +134,20 @@
     //[[NSNotificationCenter defaultCenter] postNotificationName:SGDownloadTaskExeSuspend object:nil userInfo:@{@"operation" : operation}];
 }
     
+#pragma mark - handle download
+- (void)dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response {
+    [[self oprationWithDataTask:dataTask] operateWithResponse:response];
+}
+
+- (void)dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data {
+    [[self oprationWithDataTask:dataTask] operateWithReceivingData:data];
+}
+
+
+- (void)task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
+    [[self oprationWithDataTask:task] operateWithComplete:error];
+}
+
 #pragma mark - query operation
 - (mixDownloadOperation *)operationWithUrl:(NSString *)url{
     __block mixDownloadOperation *operation = nil;
@@ -148,6 +162,20 @@
     return operation;
 }
 
+// 寻找operation
+- (mixDownloadOperation *)oprationWithDataTask:(NSURLSessionTask *)dataTask {
+    __block mixDownloadOperation *operation = nil;
+    
+    [self.operations enumerateObjectsUsingBlock:^(mixDownloadOperation * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
+        if (obj.dataTask == dataTask) {
+            operation = obj;
+            *stop = YES;
+        }
+    }];
+    
+    return operation;
+}
+
 #pragma mark - lazy load
 - (NSMutableArray<mixDownloadOperation *> *)operations {
     

+ 78 - 0
创维盒子/双子星云手机/Class/Set/uploadFile/mixDownloadManager/mixDownloadSession.m

@@ -32,6 +32,84 @@
     [self.queue startAllTasksWithSession:self.session];
 }
 
+#pragma mark - <NSURLSessionDataDelegate>
+
+// ssl 服务 证书信任
+- (void)URLSession:(NSURLSession *)session
+didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
+ completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * _Nullable credential))completionHandler{
+    if(![challenge.protectionSpace.authenticationMethod isEqualToString:@"NSURLAuthenticationMethodServerTrust"]) {
+        return;
+    }
+    
+    // 信任该插件
+    NSURLCredential *credential = [[NSURLCredential alloc] initWithTrust:challenge.protectionSpace.serverTrust];
+    // 第一个参数 告诉系统如何处置
+    completionHandler(NSURLSessionAuthChallengeUseCredential,credential);
+}
+
+//当请求协议是https的时候回调用该方法
+//Challenge 挑战 质询(受保护空间)
+//NSURLAuthenticationMethodServerTrust 服务器信任证书
+- (void)URLSession:(NSURLSession *)session
+              task:(NSURLSessionTask *)task
+didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge
+ completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * __nullable credential))completionHandler {
+    
+    if(![challenge.protectionSpace.authenticationMethod isEqualToString:@"NSURLAuthenticationMethodServerTrust"]) {
+        return;
+    }
+    
+    // 信任该插件
+    NSURLCredential *credential = [[NSURLCredential alloc] initWithTrust:challenge.protectionSpace.serverTrust];
+    // 第一个参数 告诉系统如何处置
+    completionHandler(NSURLSessionAuthChallengeUseCredential,credential);
+    
+}
+
+
+// 接受到响应调用
+- (void)URLSession:(NSURLSession *)session
+          dataTask:(NSURLSessionDataTask *)dataTask
+didReceiveResponse:(NSURLResponse *)response
+ completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler {
+    
+    // 将响应交给列队处理
+    [self.queue dataTask:dataTask didReceiveResponse:response];
+    
+    // 允许下载
+    completionHandler(NSURLSessionResponseAllow);
+}
+
+// 接受到数据碎片 的时候调用,调用多次
+- (void)URLSession:(NSURLSession *)session
+          dataTask:(NSURLSessionDataTask *)dataTask
+    didReceiveData:(NSData *)data {
+    // 接收到session 下载碎片交个列队管理
+    [self.queue dataTask:dataTask didReceiveData:data];
+}
+
+// <NSURLSessionDataDelegate> 完成下载
+- (void)URLSession:(NSURLSession *)session
+              task:(NSURLSessionTask *)task
+didCompleteWithError:(nullable NSError *)error {
+    [self.queue task:task didCompleteWithError:error];
+}
+
+- (void)URLSession:(NSURLSession *)session
+              task:(NSURLSessionTask *)task
+ needNewBodyStream:(void (^)(NSInputStream * _Nullable bodyStream))completionHandler {
+    
+}
+
+- (void)URLSession:(NSURLSession *)session
+              task:(NSURLSessionTask *)task
+   didSendBodyData:(int64_t)bytesSent
+    totalBytesSent:(int64_t)totalBytesSent
+totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend {
+    
+}
+
 #pragma mark - lazy load
 - (NSURLSession *)session {
     if (!_session) {