NSURLSessionDataDelegate代理方法实现离线断点下载,即程序意外退出时,再登陆,可以根据上次的进度继续下载.
原理:
- 边下载边写入到caches
- 每次开启下载时,设置请求头的信息:下载的位置.
#define KfileName @"123.mp4"
@interface ViewController ()<NSURLSessionDataDelegate>
@property (weak, nonatomic) IBOutlet UILabel *label;
@property (weak, nonatomic) IBOutlet UIProgressView *progress;
/** currentsize */
@property (nonatomic, assign) NSInteger currentSize;
@property (nonatomic, assign) NSInteger totalSize;
/** dataTask */
@property (nonatomic, strong) NSURLSessionDataTask *dataTask;
/** outPutStream */
@property (nonatomic, strong) NSOutputStream *outPutStream;
@end
@implementation ViewController
#pragma mark -------------------------------
#pragma mark Events
- (IBAction)startBtnClick:(id)sender {
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
//确定是否存在已经下载的文件,如存在,继续下载.
self.currentSize = [self getSize];
//new dataTask
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_02.mp4"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
//设置请求头信息
NSString *header = [NSString stringWithFormat:@"bytes=%zd-",self.currentSize];
[request setValue:header forHTTPHeaderField:@"Range"];
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request];
self.dataTask = dataTask;
[self.dataTask resume];
}
- (IBAction)suspendBtnClick:(id)sender {
[self.dataTask suspend];
}
- (IBAction)continueBtnClick:(id)sender {
[self.dataTask resume];
}
#pragma mark -------------------------------
#pragma mark methods
- (NSInteger)getSize{
//0.拼接文件全路径
NSString *fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:KfileName];
//先把沙盒中的文件大小取出来
NSDictionary *dict = [[NSFileManager defaultManager]attributesOfItemAtPath:fullPath error:nil];
NSInteger size = [[dict objectForKey:@"NSFileSize"]integerValue];
return size;
}
#pragma mark -------------------------------
#pragma mark NSURLSessionDataDelegate
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler{
//此处注意,不设置为allow,其它delegate methods将不被执行
completionHandler(NSURLSessionResponseAllow);
self.totalSize = response.expectedContentLength + self.currentSize;
//0.拼接文件全路径
NSString *fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:KfileName];
//1.创建输出流
NSOutputStream *outPutStream = [NSOutputStream outputStreamToFileAtPath:fullPath append:YES];
[outPutStream open];
self.outPutStream = outPutStream;
}
//2.当接受到服务器返回的数据的时候调用,会调用多次
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data{
self.currentSize += data.length;
CGFloat rate = 1.0 * self.currentSize / self.totalSize;
self.progress.progress = rate;
self.label.text = [NSString stringWithFormat:@"%.2f", rate];
[self.outPutStream write:data.bytes maxLength:data.length];
}
//3.当整个请求结束的时候调用,error有值的话,那么说明请求失败
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{
[self.outPutStream close];
self.outPutStream = nil;
}
@end
细节未完全处理:btn的enable状态,方法抽取等.
网友评论