大文件下载分析
在大文件的下载时,文件的下载传输时间较长,需要使用到暂停或者下载中意外退出时候仍能继续上次的下载进度.
使用的类
-
NSURLConnction
的代理方法写入沙盒中 - 使用文件句柄(指针)
NSFileHandle
在接受数据每次将句柄移动到数据末尾seekToEndOfFile
使用句柄写数据; - 在
NSMutableURLRequest
请求头中设定Range,实现断点下载; - 使用
NSFileManager
来获取文件的大小;
实现代码
- 设置相关的属性
@property (weak, nonatomic) IBOutlet UIProgressView *progressView;
/**目标文件小大*/
@property (nonatomic, assign) NSInteger totalSize;
/**当前已下载的文件小大*/
@property (nonatomic, assign) NSInteger currentSize;
/** 文件句柄*/
@property (nonatomic, strong)NSFileHandle *handle;
/** 沙盒路径 */
@property (nonatomic, strong) NSString *fullPath;
/** 连接对象 */
@property (nonatomic, strong) NSURLConnection *connect;
- 建立请求对象
在请求头里面设置要请求的文件起始位置,实现断点下载,避免重复重复请求资源
NSURL *url = [NSURL URLWithString:@"下载资源的地址"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
//设置请求头信息,告诉服务器值请求一部分数据range
/*
bytes=0-100
bytes=-100
bytes=0- 请求100之后的所有数据
*/
NSString *range = [NSString stringWithFormat:@"bytes=%zd-",self.currentSize];
[request setValue:range forHTTPHeaderField:@"Range"];
//发送请求
self.connect = [[NSURLConnection alloc]initWithRequest:request delegate:self];
- 实现代理方法
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
//1.得到文件的总大小(本次请求的文件数据的总大小 != 文件的总大小)
// self.totalSize = response.expectedContentLength + self.currentSize;
if (self.currentSize >0) {
return;
}
self.totalSize = response.expectedContentLength;
//2.写数据到沙盒中
self.fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]stringByAppendingPathComponent:@"文件路径"];
NSLog(@"%@",self.fullPath);
//3.创建一个空的文件
[[NSFileManager defaultManager] createFileAtPath:self.fullPath contents:nil attributes:nil];
//NSDictionary *dict = [[NSFileManager defaultManager]attributesOfItemAtPath:self.fullPath error:nil];
//4.创建文件句柄(指针)
self.handle = [NSFileHandle fileHandleForWritingAtPath:self.fullPath];
}
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
//1.移动文件句柄到数据的末尾
[self.handle seekToEndOfFile];
//2.写数据
[self.handle writeData:data];
//3.获得进度
self.currentSize += data.length;
//进度=已经下载/文件的总大小
NSLog(@"%f",1.0 * self.currentSize/self.totalSize);
self.progressView.progress = 1.0 * self.currentSize/self.totalSize;
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
//此处注意要关闭文件句柄
[self.handle closeFile];
self.handle = nil;
}
取消或继续下载
/**取消任务还不可逆的*/
[self.connect cancel];