基于NSURLSession多任务断点下载

孤独的香蕉.png

<h6>因为本人是个巨懒无比,最近我在寻找一个下载的第三方库,可是找了半天木有很完美的,所以只能自己动手写,虽然很懒得写但是为了活命,还是努力的动手了。</h6>

<h5>我更新了代码之前写的有些问题,也太丑了,我要对得起老爷们...


先不废话,首先队列控制还木有完全实现,因为最近工作比较忙,所以老爷们有问题给我留言就好啦,大家一起讨论,但是多任务下载,获取下载进度,获取下载速度,暂停继续都已经OK了。下面是调用,先看看是不是各位老爷们要的。

downLoad.gif
[[LBCDownLoadManager shredManager]downLoad:URL
                                          fileName:@"你下载任务的名字如:苍老师.avi"
                                          progress:^(CGFloat progress, NSString *sizeString, NSString *speedString) {
                                              NSLog(@"下载进度: %f",progress);
                                              NSLog(@"%@",sizeString);
                                              NSLog(@"下载速度: %@",speedString);
                                          } success:^(NSString *filePath) {
                                              
                                          } failure:^(NSError *error) {
                                              
                                          }];

<h6>第一个参数就是下载的URL 第二个为你下载文件的文件名,然后返回参数老爷们自己看吧,你们这么聪明就不用我介绍了,再往下是成功后返回文件路径。拿到后你们可以随意做你们想做的事情了,失败后会有error,这里说下,暂停也会走failure这个block,所以大家需要判断下,稍候我会完善下。或者老爷们自己动手完善下也可以。


<h5>接下来说下思路吧,我用的是NSURLSessionDataTask来实现的断点下载。

<h6>首先获得NSURLSession对象并且<NSURLSessionTaskDelegate>遵守这个代理协议

-(NSURLSession *)LBCSession{
    if (!_LBCSession) {
         //创建config对象
        NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
        //创建session对象,并添加到主队列中,当然各位老爷也可以不添加到主队列.
        _LBCSession = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    }
    return _LBCSession;
}

<h6>思路是这样的,取得URLString也就是下载的URL的哈希值作为当前任务的唯一标识,在做好下载准备的时候我会在本地沙盒中创建一个plist文件,存储已经开始下载文件的已下载大小,key为URLString的哈希,这样如果下载过程中断开网络,等下次连接到网络的时候我也知道这次我下载了多少,再从上次断开的地方接着下载就OK了

#pragma mark - 下载方法
/**
 *  断点下载
 *
 *  @param urlString        下载的链接
 *  @param destinationPath  下载的文件的保存路径
 *  @param  process         下载过程中回调的代码块,会多次调用
 *  @param  completion      下载完成回调的代码块
 *  @param  failure         下载失败的回调代码块
 */
-(void)downloadWithUrlString:(NSString *)urlString toFileName:(NSString *)fileName process:(ProcessHandle)process completion:(CompletionHandle)completion failure:(FailureHandle)failure{
    if(urlString&&fileName)
    {
        self.url_string=urlString;
        _fileName=fileName;
        _process=process;
        _completion=completion;
        _failure=failure;
        //判断是否已经下载完成
        if ([self getAllLength:urlString.hash]==[self getFileDownloadedLength:urlString.hash]&&[self getFileDownloadedLength:urlString.hash]>0) {
            if (completion) {
                completion();
            }
            if (process) {
                process(1.0,[self filesSize:urlString],@"0kb/s");
            }
            return;
        }
        
        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:urlString]];
        // 设置请求头
        NSString *range = [NSString stringWithFormat:@"bytes=%zd-", [self getFileDownloadedLength:urlString.hash]];
        [request setValue:range forHTTPHeaderField:@"Range"];
        // 创建一个Data任务
        NSURLSessionDataTask *task = [self.LBCSession dataTaskWithRequest:request];
        // 设置下载任务的唯一标示
        [task setValue:@(urlString.hash) forKeyPath:@"taskIdentifier"];
        LBCDownLoadModel *lbc_download = [[LBCDownLoadModel alloc]init];
        lbc_download.task = task;
        lbc_download.fileName = fileName;
        lbc_download.ProcessHandle = process;
        lbc_download.CompetionHandle = completion;
        lbc_download.FailureHandle = failure;
        [self.downloadDic setValue:lbc_download forKey:@(urlString.hash).stringValue];
        [task resume];
        
    }
}

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:URLString]];建立请求开始为正式创建下载任务,上面为判断的是否已经下载和任务继续暂停。
上述代码中的URLString.hash为url的哈希值,去这个哈希值为的是做唯一标示,在多任务处理数据时可以根据唯一标识来判断是哪个任务。

<h5>接下来为NSURLSessionDataTask的代理方法

#pragma mark Delegate
// 收到响应
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSHTTPURLResponse *)
response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler {

    LBCDownLoadModel *lbc_Model = [self.downloadDic valueForKey:@(dataTask.taskIdentifier).stringValue];
    NSUInteger allLength = response.expectedContentLength + [self getFileDownloadedLength:dataTask.taskIdentifier];
    [self setAllLength:allLength WithTag:dataTask.taskIdentifier];
    NSString *fullPath = [self createCachePath:dataTask.taskIdentifier];
    // 创建流
    NSOutputStream *stream = [NSOutputStream outputStreamToFileAtPath:fullPath append:YES];
    lbc_Model.stream = stream;
    lbc_Model.allLength = allLength;
    [lbc_Model.stream open];
    completionHandler(NSURLSessionResponseAllow);
}

// 接受数据(会多次调用)
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data {
    
    LBCDownLoadModel *lbc_Model = [self.downloadDic valueForKey:@(dataTask.taskIdentifier).stringValue];
    if (lbc_Model) {
        if (lbc_Model.stateBlock) {
            lbc_Model.stateBlock(LBCDownloadStateRunning);
        }
        [lbc_Model.stream write:data.bytes maxLength:data.length];
        CGFloat scale = (double)[self getFileDownloadedLength:dataTask.taskIdentifier] / lbc_Model.allLength;
        if (lbc_Model.progressBlock) {
            //计算网速
            NSString *speedString=@"0.00Kb/s";
            NSString *growString=[LBCDownLoad convertSize:_growth];
            speedString=[NSString stringWithFormat:@"%@/s",growString];
            lbc_Model.progressBlock(scale,[self getFileDownloadedLength:dataTask.taskIdentifier],speedString);
        }
    }
    
}

然后是计算下载速度,其实很简单,就是用当前这一秒的下载数据大小减去前一秒的下载数据大小,就是下载速度啦

- (instancetype)init
{
    self = [super init];
    if (self) {
        _timer=[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(getGrowthSize) userInfo:nil repeats:YES];
        [[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes];
    }
    return self;
}

-(void)getGrowthSize
{
    NSInteger size=[self getFileDownloadedLength:self.url.hash];
    _growth=size-_lastSize;
    _lastSize=size;
}

代码在这里
https://github.com/gx921016/LBCoreNet.git


最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,240评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,328评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,182评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,121评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,135评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,093评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,013评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,854评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,295评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,513评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,678评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,398评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,989评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,636评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,801评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,657评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,558评论 2 352

推荐阅读更多精彩内容