Skip to content

Latest commit

 

History

History
72 lines (61 loc) · 3 KB

断点续传功能该怎么实现?.md

File metadata and controls

72 lines (61 loc) · 3 KB

断点续传功能该怎么实现?

对于断点下载需要考虑几个问题:

  • 如何暂停下载,暂停后,如何继续下载?
  • 下载失败后,如何恢复下载?
  • 应用被用户杀掉后,如何恢复之前的下载?

如何暂停下载,暂停后,如何继续下载?

第一种方法 使用cancelByProducingResumeData

/* 对某一个NSURLSessionDownloadTask取消下载,取消后会回调给我们 resumeData,
    * resumeData包含了下载任务的一些状态,之后可以用户恢复下载
   */
   - (void)cancelByProducingResumeData:(void (^)(NSData * resumeData))completionHandler;

调用该方法会触发以下方法,会附带resumeData,用于恢复。

 - (void)URLSession:(NSURLSession *)session
              task:(NSURLSessionTask *)task
didCompleteWithError:(NSError *)error 

恢复下载的方法

//通过之前保存的resumeData,获取断点的NSURLSessionTask,调用resume恢复下载
NSURLSessionDownloadTask *task = [[self backgroundURLSession] downloadTaskWithResumeData:resumeData];
[task resume];

第二种方法 使用NSURLSessionDownloadTasksuspend方法

//暂停
[self.downloadTask suspend];
//恢复
[self.downloadTask resume];

下载失败后,如何恢复下载?

/* 该方法下载成功和失败都会回调,只是失败的是error是有值的,
  * 在下载失败时,error的userinfo属性可以通过NSURLSessionDownloadTaskResumeData
  * 这个key来取到resumeData(和上面的resumeData是一样的),再通过resumeData恢复下载
  */
 - (void)URLSession:(NSURLSession *)sessiona
              task:(NSURLSessionTask *)task
didCompleteWithError:(NSError *)error {
    if (error) {
        // check if resume data are available
        if ([error.userInfo objectForKey:NSURLSessionDownloadTaskResumeData]) {
            NSData *resumeData = [error.userInfo objectForKey:NSURLSessionDownloadTaskResumeData];
            NSURLSessionTask *task = [[self backgroundURLSession] downloadTaskWithResumeData:resumeData];
            [task resume];
        }
    }
}

应用被用户杀掉后,如何恢复之前的下载?

在应用被杀掉前,iOS系统保存应用下载sesson的信息,在重新启动应用,并且创建和之前相同identifiersession时(苹果通过identifier找到对应的session数据),iOS系统会对之前下载中的任务进行依次回调URLSession:task:didCompleteWithError:方法,之后可以使用上面提到的下载失败时的处理方法进行恢复下载

**PS:**以上是对于NSURLSession,那么在iOS7.0之前使用NSURLConnection则应该新增一个currentLength属性,时刻记录当前下载文件的长度。然后下载时通过设置http头``Range将当前进度传过去。告诉服务端从哪开始下载。

NSMutableURLRequest *mRequest = [NSMutableURLRequest requestWithURL:url];
NSString *range = [NSString stringWithFormat:@"bytes=%lld-",self.currentLength];
[mRequest setValue:range forHTTPHeaderField:@"Range"];