基于NSURLSession多任務斷點下載

孤獨的香蕉.png

<h6>因為本人是個巨懶無比赶么,最近我在尋找一個下載的第三方庫隘击,可是找了半天木有很完美的,所以只能自己動手寫箱锐,雖然很懶得寫但是為了活命比勉,還是努力的動手了。</h6>

<h5>我更新了代碼之前寫的有些問題驹止,也太丑了浩聋,我要對得起老爺們...


先不廢話,首先隊列控制還木有完全實現(xiàn)臊恋,因為最近工作比較忙衣洁,所以老爺們有問題給我留言就好啦,大家一起討論抖仅,但是多任務下載坊夫,獲取下載進度砖第,獲取下載速度,暫停繼續(xù)都已經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來實現(xiàn)的斷點下載。

<h6>首先獲得NSURLSession對象并且<NSURLSessionTaskDelegate>遵守這個代理協(xié)議

-(NSURLSession *)LBCSession{
    if (!_LBCSession) {
         //創(chuàng)建config對象
        NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
        //創(chuàng)建session對象唆阿,并添加到主隊列中,當然各位老爺也可以不添加到主隊列.
        _LBCSession = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    }
    return _LBCSession;
}

<h6>思路是這樣的益涧,取得URLString也就是下載的URL的哈希值作為當前任務的唯一標識,在做好下載準備的時候我會在本地沙盒中創(chuàng)建一個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"];
        // 創(chuàng)建一個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]];建立請求開始為正式創(chuàng)建下載任務记舆,上面為判斷的是否已經下載和任務繼續(xù)暫停鸽捻。
上述代碼中的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];
    // 創(chuàng)建流
    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


最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市碧磅,隨后出現(xiàn)的幾起案子痰滋,更是在濱河造成了極大的恐慌摘能,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件敲街,死亡現(xiàn)場離奇詭異团搞,居然都是意外死亡,警方通過查閱死者的電腦和手機多艇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進店門逻恐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人峻黍,你說我怎么就攤上這事复隆。” “怎么了姆涩?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵挽拂,是天一觀的道長。 經常有香客問我骨饿,道長亏栈,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任宏赘,我火速辦了婚禮绒北,結果婚禮上,老公的妹妹穿的比我還像新娘察署。我一直安慰自己闷游,他們只是感情好,可當我...
    茶點故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布贴汪。 她就那樣靜靜地躺著脐往,像睡著了一般。 火紅的嫁衣襯著肌膚如雪扳埂。 梳的紋絲不亂的頭發(fā)上钙勃,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天,我揣著相機與錄音聂喇,去河邊找鬼辖源。 笑死,一個胖子當著我的面吹牛希太,可吹牛的內容都是我干的克饶。 我是一名探鬼主播,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼誊辉,長吁一口氣:“原來是場噩夢啊……” “哼矾湃!你這毒婦竟也來了?” 一聲冷哼從身側響起堕澄,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤邀跃,失蹤者是張志新(化名)和其女友劉穎霉咨,沒想到半個月后,有當地人在樹林里發(fā)現(xiàn)了一具尸體拍屑,經...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡途戒,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了僵驰。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片喷斋。...
    茶點故事閱讀 38,605評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡窑滞,死狀恐怖豆巨,靈堂內的尸體忽然破棺而出呻待,到底是詐尸還是另有隱情驯遇,我是刑警寧澤,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布侧甫,位于F島的核電站喜鼓,受9級特大地震影響珠洗,放射性物質發(fā)生泄漏诺核。R本人自食惡果不足惜抄肖,卻給世界環(huán)境...
    茶點故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望猪瞬。 院中可真熱鬧憎瘸,春花似錦入篮、人聲如沸陈瘦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽痊项。三九已至,卻和暖如春酥诽,著一層夾襖步出監(jiān)牢的瞬間鞍泉,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工肮帐, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留咖驮,地道東北人。 一個月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓训枢,卻偏偏與公主長得像托修,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子恒界,可洞房花燭夜當晚...
    茶點故事閱讀 43,472評論 2 348

推薦閱讀更多精彩內容