// 文件离线断点下载
#import "ViewController.h"
#define FileName @"abc.mp4"
#define FileLength @"mm.chd"
@interface ViewController () <NSURLSessionDataDelegate>
@property(nonatomic, assign)NSInteger currentLenght;
@property (weak, nonatomic) IBOutlet UIProgressView *progress;
@property(nonatomic, assign)NSInteger totalLenght;
/** 输出流 */
@property (nonatomic , strong)NSOutputStream *stream;
/** 请求任务 */
@property (nonatomic , strong) NSURLSessionDataTask *dataTask;
/** 回话对象 */
@property (nonatomic , strong)NSURLSession *session;
@end
@implementation ViewController
-(void)viewDidLoad
{
[super viewDidLoad];
//刷新进度条
NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
NSString *fullPath = [caches stringByAppendingPathComponent:FileLength];
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithContentsOfFile:fullPath];
if (dict)
{
//取出文件总大小
NSInteger total = [[dict objectForKey:FileLength] integerValue];
self.totalLenght = total;
}
if (self.totalLenght != 0)
{
self.progress.progress = 1.0 * [self getCurrent] / self.totalLenght;
}
}
/**
* 获取当前已下载文件的大小
*/
-(NSInteger)getCurrent
{
NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
NSString *fullPath = [caches stringByAppendingPathComponent:FileName];
NSFileManager *manager = [NSFileManager defaultManager];
NSDictionary *dict = [manager attributesOfItemAtPath:fullPath error:nil];
return [dict[@"NSFileSize"] integerValue];
}
/**
* 保存需要下载文件的大小(为进度条的显示准备数据)
*/
-(void)saveTotal:(NSUInteger)length
{
NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
NSString *fullPath = [caches stringByAppendingPathComponent:FileLength];
//创建一个可变字典存储下载信息
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setObject:@(length) forKey:FileLength];
[dict writeToFile:fullPath atomically:YES];
}
-(NSURLSession *)session
{
if (_session == nil)
{
_session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
}
return _session;
}
/**
* 保证每一次请求数据,dataTask指针都不为空
*/
-(NSURLSessionDataTask *)dataTask
{
if (_dataTask == nil)
{
self.currentLenght = [self getCurrent];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http:链接"]];
NSString *range = [NSString stringWithFormat:@"bytes=%zd-",self.currentLenght];
[request setValue:range forHTTPHeaderField:@"Range"];
//发送请求
_dataTask = [self.session dataTaskWithRequest:request];
}
return _dataTask;
}
/**
* 开始下载
*/
- (IBAction)beginDown:(id)sender
{
[self.dataTask resume];
}
/**
* 暂停下载
*/
- (IBAction)stopDown:(id)sender
{
[self.dataTask suspend];
}
/**
* 继续下载
*/
- (IBAction)continueDown:(id)sender
{
[self.dataTask resume];
}
#pragma mark - NSURLSessionDataDelegate
/**
* 1. 接受到服务器响应的时候调用
*/
-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler
{
//发送多次请求时,获取文件的大小会变化,保持总数据不变。
self.totalLenght = response.expectedContentLength + self.currentLenght;
//存储文件大小的信息
[self saveTotal:self.totalLenght];
//添加在缓存中
NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
//拼接路径
NSString *fullPath = [caches stringByAppendingPathComponent:FileName];
//输出流
self.stream = [[NSOutputStream alloc] initToFileAtPath:fullPath append:YES];
[self.stream open];
//告诉系统允许接收数据
completionHandler(NSURLSessionResponseAllow);
}
/**
* 2.接受到服务器返回数据的时候调用,该方法啊可能会被调用多次
*/
-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
{
//输出流写入数据
[self.stream write:data.bytes maxLength:data.length];
self.currentLenght += data.length;
self.progress.progress = 1.0 * self.currentLenght / self.totalLenght;
NSLog(@"%f",self.progress.progress);
}
/**
* 请求完成之后调用
*/
-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
[self.stream close];
self.stream = nil;
}
-(void)dealloc
{
//在不用的时候一定要调用该方法来释放,不然会有内存泄漏问题
[self.session invalidateAndCancel];
}
@end
大文件离线断点下载
最新推荐文章于 2024-03-09 12:00:00 发布