IOS文件下载一般分为大文件下载和小文件下载,一般小文件下载一般处理就可以,但是大文件下载如果不进行特殊处理的话会大量站占用内存,所以要用一些方法避免这种情况
原理: 文件边下载边写入沙盒,而不是一次性写入沙盒,这样就能避免一次大量占用内存,因为每次写入沙盒的data并不是很大,所以能很好缓解内存的压力。
准备工作,准备好几个要用到的变量,一看就知道什么用,不多说
@property(nonatomic,strong) NSFileHandle *writeHandle;
// 用来保存要下载的文件的总长度
@property(nonatomic,assign) long long totalLength;
// 用来保存当前下载的长度
@property(nonatomic,assign) long long currentLength;
@property(nonatomic,strong) UIProgressView *progessView;
如果要实现边下载边写入让我们自己写的话,肯定不简单,所以我们当然要用NSURLConnectionDataDelegate代理方法
流程:
(1)点击按钮,开始下载
// 一只猫的图片下载地址
NSURL *url=[NSURL URLWithString:@"http://image.baidu.com/search/down?tn=download&word=download&ie=utf8&fr=detail&url=http%3A%2F%2Fpic28.nipic.com%2F20130401%2F10580496_153630302101_2.jpg&thumburl=http%3A%2F%2Fimg2.imgtn.bdimg.com%2Fit%2Fu%3D3642067914%2C1635469680%26fm%3D21%26gp%3D0.jpg"];
// 创建一个请求
NSURLRequest *request=[NSURLRequest requestWithURL:url];
// 下载 自动发起一个异步请求
[NSURLConnection connectionWithRequest:request delegate:self];
(2)当下载连接成功创建,也就是连接到下载的服务器成功了,说明应该能下载,这是会调用一个代理方法,用这里的参数可以得到你要下载文件的总大小,既然能下载我们就在沙盒中创建一个0kb大小的文件,用来存储数据,明显这个数据存储在沙盒的caches文件夹,再创建一个句柄用来写入数据。
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
NSString *caches=[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)lastObject];
NSString *filepath=[caches stringByAppendingPathComponent:@"cat.jpg"];
// 先创建一个0kb文件 到沙盒
NSFileManager *mgr=[NSFileManager defaultManager];
NSLog(@"%@",filepath);
[mgr createFileAtPath:filepath contents:nil attributes:nil];
// 创建写数据的文件句柄
self.writeHandle=[NSFileHandle fileHandleForWritingAtPath:filepath];
//得到下载文件总大小
self.totalLength=response.expectedContentLength;
}
(3)开始下载数据,没下载一点数据就会自动调用一个代理方法,所以当然要把变下边写的方法写在这个代理方法里面,注意一点就好:每次写入数据要写在文件最后面,别把前面数据覆盖了
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
// 移动到文件的最后写入数据
[self.writeHandle seekToEndOfFile];
[self.writeHandle writeData:data];
self.currentLength+=data.length;
NSLog(@"下载进度%f",(double)self.currentLength/self.totalLength);
self.progessView.progress=(double)self.currentLength/self.totalLength;
}
(4)下载完毕,数据重置,收尾操作
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
self.currentLength = 0;
self.totalLength = 0;
// 关闭文件
[self.writeHandle closeFile];
self.writeHandle=nil;
}