IOS,单文件,断点下载,退出app再进入还可以继续下载

更新2016_11_1

以下Demo是存在问题的,不过不是代码问题,而是下载功能不能放在ViewController中,我的处理方法是单独建立了一个单例模式的类来控制下载过程,这样保证了后台下载的功能。

不过还是有很严重的问题:网上大多都说使用cancelByProducingResumeData方法来缓存,在IOS9中是可以的,但是因为项目需求,测试了IOS7和IOS10,在这两个版本上都是无法缓存的,再次下载时会重新下载,我之前试着打印过resumeData,发现在IOS9中打印是完整的,可是IOS7和IOS10中打印只能打印一部分,导致resumeData无法使用,我至今没发现有大神提过这个问题。

我后来是用的暂停来处理的,因为使用一个单例类来下载,就不存在暂停后销毁downloadTask和session的问题,所以直接用暂停/继续就可以了,不需要缓存,但是如果关闭手机,或者强行退出app,就会重新下载,实际上并没有实现缓存的功能,因为app赶时间,这个下载功能只是很小的一部分,所以我当时只能那样处理,如果用户强行关闭app或者断网,就必须重新下载,总之,我得到一个结论,这种简单的NSURLSession下载方式依然无法解决所谓的断点下载的问题。

————————————————————————————————————————————————————————

最近被这个功能搞死了,先是找各种框架,最初用的AFNetworking然后尝试ASIHttp,都以失败告终,网上有很多教程之类的,不是代码繁琐就是没点逻辑,感觉都是复制粘贴党,因为项目急,真是弄的我好烦,好不容易找到一片不错的,介绍的也很简单,不过也多亏了那一篇文章让我知道了两个关键的类NSURLSessionDownloadTask和NSURLSession

我这里只贴关键代码和思路,因为各个项目需求不同,其实很简单,就几行代码

一。申明变量,第一个是显示进度文字,第二个是进度条,第三四个变量是控制下载的

@property (weak, nonatomic) IBOutlet UILabel *progress;
@property (weak, nonatomic) IBOutlet UIProgressView *progressBar;
@property(nonatomic,strong)NSURLSessionDownloadTask *downloadTask;
@property(nonatomic,strong)NSURLSession *session;
二。下载的方法,这里请记住一个重要参数,resumeData,我把它存入了userdefault中,这是断点下载的关键,这个方法传入字符串urlString就行了,就是你的文件所在地址:比如http://xxx.xxx.xx/xxx.zip这种就行了,下载的时候判断userDefault中的resumeData是否存在,如果存在就使用downloadTaskWithResumeData的方法来下载(可以理解为从中途开始下载),如果为nil,那么就新建一个下载

#pragma mark - 下载
-(void)downloadWithUrl:(NSString*)urlString{
    NSURL* url = [NSURL URLWithString:urlString];
    // 得到session对象
    NSURLSessionConfiguration* cfg = [NSURLSessionConfiguration defaultSessionConfiguration]; // 默认配置
    self.session = [NSURLSession sessionWithConfiguration:cfg delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    // 创建任务
    //获取上一次下载的地方
    NSData *resumeData=[[NSUserDefaults standardUserDefaults] valueForKey:@"resumeData"];
    if(resumeData!=nil){
        self.downloadTask=[self.session downloadTaskWithResumeData:resumeData];
    }else{
        self.downloadTask = [self.session downloadTaskWithURL:url];
    }
    // 开始任务
    [self.downloadTask resume];
}


三。实现代理,这里忘了说了,要让你的viewcontroller实现NSURLSessionDownloadDelegate,这个代理主要监听两个方法,第一个是下载进度的监听,在里面更新进度条和文字,第二个是下载结束后的监听,注意:下载结束后把userDefault中的resumeData置为nil,主要是防止如果你删除了这个文件,下次重新下载如果不为nil,他会继续从resumeData的位置开始下载,此时resumeData记录的位置已经是100%了,那么他根本就不会下载了

/**
 *  每次写入沙盒完毕调用
 *  在这里面监听下载进度,totalBytesWritten/totalBytesExpectedToWrite
 *
 *  @param bytesWritten              这次写入的大小
 *  @param totalBytesWritten         已经写入沙盒的大小
 *  @param totalBytesExpectedToWrite 文件总大小
 */
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{
    float progressF=(float)totalBytesWritten/(float)totalBytesExpectedToWrite;
    self.progress.text=[NSString stringWithFormat:@"已下载%d%",(int)(progressF*100)];
    [self.progressBar setProgress:progressF];
}

/**
 *  下载完毕时调用
 *
 *  @param location 下载后的地址
 */
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location
{
 //做你要做的事情
    [[NSUserDefaults standardUserDefaults] setObject:nil forKey:@"resumeData"];
}

四。取消下载,这里最关键了!首先我点击取消下载按钮进入这个方法,直接dismiss这个界面,那些什么downloadtask之类的东西就都没了,网上那些暂停继续又没退出界面能称之为断点下载吗??咳咳吐个槽,实在被搞得很烦。注意了,cancelByProducingResumeData这个方法很重要,这个block中又一个resumeData,你可以理解为它就是记录当前下载到的位置的指针,既然有了下载位置,那就简单了,把它存入userdefault中,下载下载直接取出来,然后接着下载就行了啊,看到这里,你可以在往回看一看,应该就能明白了

- (IBAction)pauseDl:(UIButton *)sender {
    [self.downloadTask cancelByProducingResumeData:^(NSData *resumeData) {
        NSUserDefaults *userDefault = [NSUserDefaults standardUserDefaults];
        [userDefault setObject:resumeData forKey:@"resumeData"];
        [userDefault synchronize];
        self.downloadTask = nil;
    }];
    [self dismissViewControllerAnimated:NO completion:nil];

}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值