美文网首页
断点续传

断点续传

作者: 努力奔跑的小男孩 | 来源:发表于2016-11-23 20:52 被阅读19次

    能够实现下载 暂停 继续下载功能 主要使用 NSURLSessionDownloadTask

    在要实现ViewController 的.m 文件中实现如下代码:
    核心代码

    需要遵循 <NSURLSessionDownloadDelegate> 代理 实现里面的协议方法

    匿名类别中需要实现
    #import "ViewController.h"
    //引入其他文件中声明的全局变量时,使用extern 关键字
    extern void(^compeleHandle)();
    
    @interface ViewController ()<NSURLSessionDownloadDelegate>
    
    @property (weak, nonatomic) IBOutlet UIButton *downloadBtn;
    
    @property (weak, nonatomic) IBOutlet UIProgressView *progess;
    
    @property(nonatomic, strong) NSURLSession *session;//执行下载任务的session
    @property (nonatomic, strong) NSURLSessionDownloadTask *task;//下载任务
    @property (nonatomic, strong) NSData * resumData;//暂停时,产生的已经下载的数据,用于再次启动继续下载
    @end
    
    在viewDidLoad 需要实现代码
    - (void)viewDidLoad {
        [super viewDidLoad];
        //修改进度条的高度
        self.progess.transform = CGAffineTransformMakeScale(1, 3);
        self.progess.progress = 0;
    }
    
    点击下载按钮代码
    //下载
    - (IBAction)downloadClicked:(UIButton *)sender {
        
        sender.enabled = NO;
        
        //下载的资源路径
        NSURL * url = [NSURL URLWithString:@"http://dldir1.qq.com/qqfile/QQforMac/QQ_V4.0.2.dmg"];
        //创建请求对象
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        if(!_session){
            NSURLSessionConfiguration *config = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"downloadID"];
            //创建后台模式的session
            _session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]];
        }
        
        if(self.resumData != nil){
            //在上一次下载的基础上继续下载
            //在上一次下载的基础上创建任务
            _task = [_session downloadTaskWithResumeData:_resumData];
        }else{
            //新建任务下载
            //创建任务
            _task = [_session downloadTaskWithRequest:request];
        }
        //启动下载任务
        [_task resume];
    }
    
    点击暂停按钮代码
    //暂停
    - (IBAction)pauseClicked:(UIButton *)sender {
        //任务的的暂停
        [_task cancelByProducingResumeData:^(NSData * _Nullable resumeData) {
            //当前已经下载的数据:保存当前已经下载的数据,便于做续传
            _resumData = resumeData;
            //停不下来
            [_session invalidateAndCancel];//让会话实现并取消任务
            _session = nil;
        }];
        
        [self.downloadBtn setTitle:@"继续" forState:UIControlStateNormal];
        self.downloadBtn.enabled = YES;
    }
    
    下载协议方法
    //已经开始从某一个偏移量的位置下载
    -(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes
    {
        NSLog(@"已经开始下载,开始的偏移量----> %lld",fileOffset);
    }
    //下载过程中调用的方法
    -(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{
        //下载过程中我们是得不到所下载的数据的,我们只能更新下载进度
        NSLog(@"更新下载进度");
        //计算当前的下载进度
        // bytesWritten: 本次写入的数据长度
        // totalBytesWritten: 已经下载的数据总长度
        // totalBytesExpectedToWrite 数据的总长度
        // 进度 =(bytesWritten + totalBytesWritten)÷ totalBytesExpectedToWrite
        CGFloat progress = (bytesWritten + totalBytesWritten)* 1.0/ totalBytesExpectedToWrite * 1.0 ;
        //更新进度条显示的进度值
        dispatch_async(dispatch_get_main_queue(), ^{
            //更UI相关的更新,要在主线程中完成
            self.progess.progress = progress;
        });
    }
    
    //下载结束
    -(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
    {
        //下载完成,所下载的数据存放在 location 位置,我们可以通过文件操作,移动这个数据到我们需要的位置
        NSLog(@"下载完成");
        NSFileManager *fm = [NSFileManager defaultManager];
        //将要移动的目标位置,沙盒路径中的存放位置
        NSString * path = [NSString stringWithFormat:@"%@/Documents/QQ.dmg",NSHomeDirectory()];
        NSError *error = nil;
        [fm moveItemAtURL:location toURL:[NSURL fileURLWithPath:path] error:&error];
        if(!error){
            NSLog(@"移动成功,可以到沙盒路径下查看下载的文件");
            self.progess.progress = 1.0;
        }
        
    }
    
    //如果要支持后台下载,实现后台处理的协议方法
    -(void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session{
        //下载结束时,后台唤醒App之后,应该回调的第一个协议方法
        NSLog(@"后台下载完成,回调协议方法");
        if(compeleHandle){
            //回调,使得其他的后续的协议方法能正常调用
            compeleHandle();
            //通常在这儿,要结合本地推送使用,否则用户本身是发现不了任务执行完成的
        }
        
    }
    
    需要在AppDelegate 的.m 中实现代码
    #import "AppDelegate.h"
    
    void(^compeleHandle)();//用于后台任务完成时记录回调block
    
    @interface AppDelegate ()
    
    @end
    
    @implementation AppDelegate
    
    
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        // Override point for customization after application launch.
        return YES;
    }
    //让App支持后台处理任务,实现AppDelegate的后台处理协议方法
    -(void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler{
        //在后台执行的后台任务完成之后,首先调用的方法,通过该方法来唤醒APP
        //将block记录下
        compeleHandle = completionHandler;
    }
    

    相关文章

      网友评论

          本文标题:断点续传

          本文链接:https://www.haomeiwen.com/subject/yabvpttx.html