[iOS]使用iOS8.0框架下URLSession對象實現(xiàn)斷點下載功能

VideoDownLoadManager.h

//
//  VideoDownLoadManager.h
//  DowloadBreakPointDemo
//
//  Created by 郭曉敏 on 15/8/8.
//  Copyright (c) 2015年 com.jiaoxuebu.gxm. All rights reserved.
//

#import <Foundation/Foundation.h>
@class VideoModel;

@protocol VideoDownLoadManagerDelegate <NSObject>

-(void)videoDidUpdatedProgressWithVideoModel:(VideoModel *)model;

@end

@interface VideoDownLoadManager : NSObject

@property(nonatomic, weak)id<VideoDownLoadManagerDelegate>delegate;

+(instancetype)sharedInstance;

@property(nonatomic, strong)NSOperationQueue *downLoadQueue;

//  用來保存創(chuàng)建的下載管理類屋群,方面以后的對應管理
@property(nonatomic, strong)NSMutableDictionary *httpOperationDict;

@property(nonatomic, strong)NSMutableArray *downVideoArray;
#pragma mark 開始下載
-(void)startAVideoWithVideoModel:(VideoModel *)downLoadVideo;

#pragma mark 暫停下載
-(void)downloadPausewithModel:(VideoModel *)pauseModel;

#pragma mark 斷點繼續(xù)下載
-(void)downloadResumeWithModel:(VideoModel *)resumeModel;
@end

VideoDownLoadManager.m

//
//  VideoDownLoadManager.m
//  DowloadBreakPointDemo
//
//  Created by 郭曉敏 on 15/8/8.
//  Copyright (c) 2015年 com.jiaoxuebu.gxm. All rights reserved.
//

#import "VideoDownLoadManager.h"
#import "VideoModel.h"
#import "VideoDownLoadOperation.h"

@interface VideoDownLoadOperation ()

@end

static VideoDownLoadManager *manager;
@implementation VideoDownLoadManager
+(instancetype)sharedInstance
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if (manager == nil) {
            manager = [[VideoDownLoadManager alloc] init];
            manager.httpOperationDict = [NSMutableDictionary dictionary];
            manager.downVideoArray = [NSMutableArray array];

        }
    });

    return manager;
}
/*經過研究,AFN 的繼續(xù)和暫停下載不是線程安全的,使用會經常出錯*/
#pragma mark 開始下載
-(void)startAVideoWithVideoModel:(VideoModel *)downLoadVideo
{
    NSLog(@"........%@", CachesPath);
    if (!self.downLoadQueue) {
        self.downLoadQueue = [[NSOperationQueue alloc] init];
        self.downLoadQueue.maxConcurrentOperationCount = 3;
    }
    VideoDownLoadOperation *ope = [[VideoDownLoadOperation alloc] initWithDownLoadVideoModel:downLoadVideo];
    ope.updateBlock = ^(VideoModel *model){
        if (self.delegate && [self.delegate respondsToSelector:@selector(videoDidUpdatedProgressWithVideoModel:)]) {
            [self.delegate videoDidUpdatedProgressWithVideoModel:model];
        }
    };

    [self.httpOperationDict setObject:ope forKey:downLoadVideo.flv];
    [self.downLoadQueue addOperation:ope];
    [self.downVideoArray addObject:downLoadVideo];
    [[NSNotificationCenter defaultCenter] postNotificationName:k_newVideoDidStartDown object:nil];
}

#pragma mark 暫停下載
-(void)downloadPausewithModel:(VideoModel *)pauseModel
{

    
    VideoDownLoadOperation *ope = [self.httpOperationDict objectForKey:pauseModel.flv];
    if (!ope.isFinished) {
        [ope downLoadPause];
    }

}

#pragma mark 斷點繼續(xù)下載
-(void)downloadResumeWithModel:(VideoModel *)resumeModel
{
    VideoDownLoadOperation *ope = [self.httpOperationDict objectForKey:resumeModel.flv];
    if (!ope.isFinished) {
        [ope downLoadResume];
    }
}

@end

VideoDownLoadOperation.h

//
//  VideoDownLoadOperation.h
//  DowloadBreakPointDemo
//
//  Created by 郭曉敏 on 15/8/9.
//  Copyright (c) 2015年 com.jiaoxuebu.gxm. All rights reserved.
//

#import <Foundation/Foundation.h>
@class VideoModel;
typedef void(^VIDEODidUpateBlcok)(VideoModel *);

@interface VideoDownLoadOperation : NSOperation
-(instancetype)initWithDownLoadVideoModel:(VideoModel *)videoModel;

@property(nonatomic, copy)VIDEODidUpateBlcok updateBlock;
// 暫停
-(void)downLoadPause;
// 恢復
-(void)downLoadResume;
@end

VideoDownLoadOperation.m

//
//  VideoDownLoadOperation.m
//  DowloadBreakPointDemo
//
//  Created by 郭曉敏 on 15/8/9.
//  Copyright (c) 2015年 com.jiaoxuebu.gxm. All rights reserved.
//

#import "VideoDownLoadOperation.h"
#import "VideoModel.h"
@interface VideoDownLoadOperation ()<NSURLSessionDelegate,NSURLSessionDownloadDelegate>
{
    // 用于判斷一個任務是否正在下載
    BOOL _isDownLoading;

}
@property(nonatomic, strong)VideoModel *downLoadVideoModel;
// 定義 session
@property(nonatomic, strong)NSURLSession *currentSession;
// 用于可恢復的下載任務的數(shù)據(jù)
@property(nonatomic, strong)NSData *partialData;
// 可恢復的下載任務
@property(nonatomic, strong)NSURLSessionDownloadTask *task;
@end

@implementation VideoDownLoadOperation
-(instancetype)initWithDownLoadVideoModel:(VideoModel *)videoModel
{
    self = [super init];
    if (self) {
        self.downLoadVideoModel = videoModel;
    }
    return self;
}

-(void)main
{

    NSURLSessionConfiguration *configure = [NSURLSessionConfiguration defaultSessionConfiguration];

    self.currentSession = [NSURLSession sessionWithConfiguration:configure delegate:self delegateQueue:nil];
    self.currentSession.sessionDescription = self.downLoadVideoModel.flv;
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:self.downLoadVideoModel.flv]];
    self.task = [self.currentSession downloadTaskWithRequest:request];
    [self.task resume];
    _isDownLoading = YES;
    while (_isDownLoading) {
        [[NSRunLoop currentRunLoop] runUntilDate:[NSDate distantFuture]];
    }
    self.partialData = nil;
}
// 暫停
-(void)downLoadPause
{
    NSLog(@"暫停");
    [self.task suspend];
}
// 恢復
-(void)downLoadResume
{
    NSLog(@"恢復下載");
    [self.task resume];
}

#pragma mark delegate(task)
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
{

    NSLog(@"path = %@", location.path);
    // 將臨時文件剪切或者復制到 caches 文件夾
    NSFileManager *manager = [NSFileManager defaultManager];

    NSString *appendPath = [NSString stringWithFormat:@"/%@.mp4",self.downLoadVideoModel.title];
    NSString *file = [CachesPath stringByAppendingString:appendPath];

    [manager moveItemAtPath:location.path toPath:file error:nil];
    
    _isDownLoading = NO;

    // 下載完成發(fā)送通知
    dispatch_async(dispatch_get_main_queue(), ^{
        [[NSNotificationCenter defaultCenter] postNotificationName:k_videoDidDownedFinishedSuccess object:self.downLoadVideoModel];
        self.downLoadVideoModel.isDownFinished = YES;
    });

}

-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
    NSLog(@"-----%f", bytesWritten  * 1.0 / totalBytesExpectedToWrite);
    self.downLoadVideoModel.progressValue = totalBytesWritten / (double)totalBytesExpectedToWrite;
    dispatch_async(dispatch_get_main_queue(), ^{
        if (self.updateBlock) {
            self.updateBlock(self.downLoadVideoModel);
        }
    });
    
}

-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes
{
    NSLog(@"%.0f", fileOffset /(CGFloat) expectedTotalBytes);
}

@end
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末航背,一起剝皮案震驚了整個濱河市俊扳,隨后出現(xiàn)的幾起案子过咬,更是在濱河造成了極大的恐慌她我,老刑警劉巖勾徽,帶你破解...
    沈念sama閱讀 217,907評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異谓谦,居然都是意外死亡贫橙,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,987評論 3 395
  • 文/潘曉璐 我一進店門反粥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來料皇,“玉大人,你說我怎么就攤上這事星压〖粒” “怎么了?”我有些...
    開封第一講書人閱讀 164,298評論 0 354
  • 文/不壞的土叔 我叫張陵娜膘,是天一觀的道長逊脯。 經常有香客問我,道長竣贪,這世上最難降的妖魔是什么军洼? 我笑而不...
    開封第一講書人閱讀 58,586評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮演怎,結果婚禮上匕争,老公的妹妹穿的比我還像新娘。我一直安慰自己爷耀,他們只是感情好甘桑,可當我...
    茶點故事閱讀 67,633評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著歹叮,像睡著了一般跑杭。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上咆耿,一...
    開封第一講書人閱讀 51,488評論 1 302
  • 那天德谅,我揣著相機與錄音,去河邊找鬼萨螺。 笑死窄做,一個胖子當著我的面吹牛,可吹牛的內容都是我干的慰技。 我是一名探鬼主播椭盏,決...
    沈念sama閱讀 40,275評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼惹盼!你這毒婦竟也來了庸汗?” 一聲冷哼從身側響起惫确,我...
    開封第一講書人閱讀 39,176評論 0 276
  • 序言:老撾萬榮一對情侶失蹤手报,失蹤者是張志新(化名)和其女友劉穎蚯舱,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體掩蛤,經...
    沈念sama閱讀 45,619評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡枉昏,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,819評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了揍鸟。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片兄裂。...
    茶點故事閱讀 39,932評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖阳藻,靈堂內的尸體忽然破棺而出晰奖,到底是詐尸還是另有隱情,我是刑警寧澤腥泥,帶...
    沈念sama閱讀 35,655評論 5 346
  • 正文 年R本政府宣布匾南,位于F島的核電站,受9級特大地震影響蛔外,放射性物質發(fā)生泄漏蛆楞。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,265評論 3 329
  • 文/蒙蒙 一夹厌、第九天 我趴在偏房一處隱蔽的房頂上張望豹爹。 院中可真熱鬧,春花似錦矛纹、人聲如沸臂聋。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,871評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽逻住。三九已至,卻和暖如春迎献,著一層夾襖步出監(jiān)牢的瞬間瞎访,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,994評論 1 269
  • 我被黑心中介騙來泰國打工吁恍, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留扒秸,地道東北人。 一個月前我還...
    沈念sama閱讀 48,095評論 3 370
  • 正文 我出身青樓冀瓦,卻偏偏與公主長得像伴奥,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子翼闽,可洞房花燭夜當晚...
    茶點故事閱讀 44,884評論 2 354

推薦閱讀更多精彩內容