123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248 |
- //
- // mixDownloadOperation.m
- // 双子星云手机
- //
- // Created by xd h on 2024/6/27.
- //
- #import "mixDownloadOperation.h"
- #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 {
-
- if (self = [super init]) {
- _url = url;
- // 初始化下载信息
- _currentSize = [self getFileSizeWithURL:url];
-
- // 偏好设置里面存储总数据
- _totalSize = [mixDownloadCacheManager totalSizeWith:url];
-
- _timeStamp = [iTools getNowTimeStamp];
- // 校验
- if (self.currentSize == self.totalSize && self.totalSize != 0) {
- return nil;
- }
-
- _downloadState = DownloadStateWaiting;
- [mixDownloadCacheManager saveFileInfoWithDict:[self downLoadInfoWithFinished:NO]];
-
- _dataTask = [session mix_downloadDataTaskWithURLString:url startSize:_currentSize];
- }
- return _dataTask ? self : nil;
- }
- #pragma mark - setups
- - (int64_t)getFileSizeWithURL:(NSString *)url {
- // // md5文件名加密
- // NSString *md5FielName = [[url lastPathComponent] stringByDeletingPathExtension];
- // // 获取后缀名
- // NSArray *subString = [[url lastPathComponent] componentsSeparatedByString:@"."];
-
- // 拼接后缀名
- NSString *urlFileName = [url lastPathComponent];
- NSString * decodeUrlFileName= [urlFileName stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
- self.fileName = decodeUrlFileName;
-
- // 创建文件储存路径
- if (![[NSFileManager defaultManager] fileExistsAtPath:[mixDownloadCacheManager getFullDirector]]) {
- [[NSFileManager defaultManager] createDirectoryAtPath:[mixDownloadCacheManager getFullDirector] withIntermediateDirectories:YES attributes:nil error:nil];
- }
- // 设置下载路径
- self.fullPath = [[mixDownloadCacheManager getFullDirector] stringByAppendingPathComponent:self.fileName];
-
- // 获取下载进度
- NSDictionary *fileInfo = [[NSFileManager defaultManager] attributesOfItemAtPath:self.fullPath error:nil];
- // 获取已下载的长度
- 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
- // 构造回调信息
- - (NSDictionary *)downLoadInfoWithFinished:(BOOL)finished {
- HLog(@"downloadState:%zd", self.downloadState);
- return @{
- @"url" : self.url,
- @"fileName" : self.fileName,
- @"fullPath" : self.fullPath,
- @"currentSize" : @(self.currentSize),
- @"totalSize" : @(self.totalSize),
- @"fileType" : @(self.fileType),
- @"timeStamp" : @(self.timeStamp),
- @"downloadState" : @(self.downloadState),
- @"isFinished" : @(finished)
- };
- }
- @end
|