#import <UIKit/UIKit.h>
@interface ViewController :UIViewController<NSURLConnectionDataDelegate>
{
BOOL isDownLoad;//标识是否正在下载
double receiveTotal;//已经接收数据总的大小
}
@property (nonatomic,assign)double totalLength;//下载数据的总的大小
@property (nonatomic,strong)NSMutableData *receiveData;//接收的总数据
@property (weak, nonatomic) IBOutletUIProgressView *progressView;//进度条
@property (weak, nonatomic) IBOutletUILabel *progressLabel;//下载比例
@property (nonatomic,copy)NSString *filePath;//文件存储路径
@property (nonatomic,strong)NSURLConnection *connection;//网络请求对象
@end
#import "ViewController.h"
@interfaceViewController ()
@end
@implementationViewController
/*
下载性能优化
使用一个缓冲Data存储下载数据,当缓冲的数据>500KB时,将此缓冲数据写入文件,并且清除缓存数据,以节约内存空间
*/
/*
断点续传的实现思路:
1. 暂停的时候,记录下载的暂停位置
2. 继续下载时,设置下载的起始位置
http协议的请求头的设置:
Range : bytes=0-499 表示头500个字节
Range : bytes=500-999 表示第二个500字节
Range : bytes=-500 表示最后500个字节
Range : bytes=500- 表示500字节以后的范围
Range : bytes=0-0,-1 第一个和最后一个字节
3. 续传写入文件时,总是从文件末尾追加写入文件
*/
- (void)viewDidLoad {
[superviewDidLoad];
// Do any additional setup after loadingthe view, typically from a nib.
//获取下载文件的存储地址
NSLog(@"%@",NSHomeDirectory());
//取得已经下载文件的大小和文件总得大小
NSUserDefaults *userDefauts = [NSUserDefaultsstandardUserDefaults];
receiveTotal = [[userDefauts objectForKey:@"ReceiveTotal"] doubleValue];
_totalLength = [[userDefauts objectForKey:@"Total"] doubleValue];
//显示上一次下载的进度
if (_totalLength > 0) {
CGFloat progress = receiveTotal / _totalLength;
self.progressView.progress = progress;
self.progressLabel.text = [NSStringstringWithFormat:@"%.2f%%",progress];
}
}
- (IBAction)downLoadAction:(UIButton *)sender {
if (!isDownLoad) {
//构建URL地址
NSURL *url = [NSURLURLWithString:@"http://free2.macx.cn:8182/tools/other4/iStatMenus511b17.dmg"];
//构建NSURLRequest请求
NSMutableURLRequest *request = [NSMutableURLRequestrequestWithURL:url];
//设置断点续传
if (receiveTotal > 0) {
//设置续传下载的位置
NSString *value = [NSStringstringWithFormat:@"bytes=%d-",(int)receiveTotal];
[request setValue:value forHTTPHeaderField:@"Range"];
}
//发送异步请求
_connection = [NSURLConnectionconnectionWithRequest:request delegate:self];
isDownLoad = YES;
//获取字符串-----获取当前要下载的文件的绝对地址
NSString *urlStr = url.absoluteString;
//获取urlStr的最后一部分
NSString *fileName = [urlStr lastPathComponent];
//写入文件
_filePath = [NSHomeDirectory() stringByAppendingFormat:@"/Documents/%@",fileName];
//判断文件是否已经存在,如果不存在,需要创建
if (![[NSFileManagerdefaultManager] fileExistsAtPath:_filePath]) {
//创建文件
[[NSFileManagerdefaultManager] createFileAtPath:_filePathcontents:nilattributes:nil];
}
}
}
#pragma mark-NSURLConnectionDataDelegate
//服务器响应了
- (void)connection:(NSURLConnection *)connectiondidReceiveResponse:(NSHTTPURLResponse *)response
{
//初始化
self.receiveData = [[NSMutableDataalloc] init];
//判断文件总的大小是否为0,如果为0,说明XO能够起始位置下载,需要获取文件的大小
if (_totalLength == 0) {
//获取所有的响应头
NSDictionary *fields = response.allHeaderFields;
//获取数据的总的大小
NSNumber *dataTotal = [fields objectForKey:@"Content-Length"];
_totalLength = [dataTotal doubleValue];
// NSLog(@"_totalLength is%.2f",_totalLength);
}
}
//接收数据
- (void)connection:(NSURLConnection *)connectiondidReceiveData:(NSData *)data
{
[self.receiveDataappendData:data];
//已经接收数据总的大小 / 总数据的大小 =下载进度
receiveTotal += data.length;
double progress = receiveTotal / _totalLength;
//刷新UI
self.progressLabel.text = [NSStringstringWithFormat:@"%.2f%%",progress * 100];
self.progressView.progress = progress;
if (self.receiveData.length >= 500 * 1000) {
//往文件路径中写入数据----调用方法
[selfappendFileData:self.receiveData];
//清空数据
self.receiveData.data = nil;
}
}
//数据传输完成
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
//将最后一个文件数据写入文件
if (self.receiveData.length < 500 * 1000) {
//调用写入数据方法
[selfappendFileData:self.receiveData];
[self.receiveDatasetData:nil];
}
_progressLabel.text = @"下载完成";
isDownLoad = NO;
}
- (void)appendFileData:(NSData *)data
{
if (data.length == 0) {
return;
}
//使用NSFileManager写入文件,此此文件比粗已经创建,NSFileHandle是不会创建文件的
NSFileHandle *fileHandle = [NSFileHandlefileHandleForWritingAtPath:_filePath];
//将数据插入到写入点
[fileHandle seekToEndOfFile];
[fileHandle writeData:data];
//关闭文件,确保写入完成
[fileHandle closeFile];
}
//暂停下载
- (IBAction)pauseDownLoadAction:(UIButton *)sender {
//取消下载
[_connectioncancel];
_connection = nil;
//将缓存数据写入文件中
[selfappendFileData:self.receiveData];
//本地保存已经下载文件的大小和文件的总的大小
NSUserDefaults *userDefaults = [NSUserDefaultsstandardUserDefaults];
[userDefaults setObject:@(receiveTotal)forKey:@"ReceiveTotal"];
[userDefaults setObject:@(_totalLength)forKey:@"ToTal"];
//将数据同步写入文件
[userDefaults synchronize];
isDownLoad = NO;
}
@end
原文:http://10585085.blog.51cto.com/10575085/1693321