一、Range简单说明
通过设置请求头Range可以指定每次从网路下载数据包的大小
Range示例
bytes=0-499 从0到499的头500个字节
bytes=500-999 从500到999的第二个500字节
bytes=500- 从500字节以后的所有字节
bytes=-500 最后500个字节
bytes=500-599,800-899 同时指定几个范围
Range小结
- 用于分隔
前面的数字表示起始字节数
后面的数组表示截止字节数,没有表示到末尾
, 用于分组,可以一次指定多个Range,不过很少用
二、代码示例
#import "YYViewController.h"
@interface YYViewController ()
//文件数据
@property(nonatomic,strong)NSMutableData *fileData;
//文件句柄
@property(nonatomic,strong)NSFileHandle *writeHandle;
//当前获取到的数据长度
@property(nonatomic,assign)long long currentLength;
//完整数据长度
@property(nonatomic,assign)long long sumLength;
//是否正在下载
@property(nonatomic,assign,getter = isdownLoading)BOOL downLoading;
//请求对象
@property(nonatomic,strong)NSURLConnection *cnnt;
//获取按钮
@property (weak, nonatomic) IBOutlet UIButton *btn;
//获取进度条
@property (weak, nonatomic) IBOutlet UIProgressView *progress;
//按钮点击事件
- (IBAction)star;
@end
@implementation YYViewController
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (IBAction)star {
//当下载完成后,点击按钮文字变为已下载
//判断当前是否正在下载
if (self.isdownLoading) {//如果当前正在下载,那么点击按钮,按钮变为暂停状态
[self.btn setTitle:@"下载" forState:UIControlStateNormal];
self.downLoading=NO;
//取消发送请求
[self.cnnt cancel];
self.cnnt=nil;
}else
{//如果当前没有下载,那么点击按钮,开始或者是继续下载
[self.btn setTitle:@"暂停" forState:UIControlStateNormal];
self.downLoading=YES;
//创建下载路径
NSURL *url=[NSURL URLWithString:@"http://192.168.1.53:8080/MJServer/resources/video.zip"];
//创建一个请求
// NSURLRequest *request=[NSURLRequest requestWithURL:url];
NSMutableURLRequest *request=[NSMutableURLRequest requestWithURL:url];
//设置请求头信息
//self.currentLength字节部分重新开始读取
NSString *value=[NSString stringWithFormat:@"bytes=%lld-",self.currentLength];
[request setValue:value forHTTPHeaderField:@"Range"];
//发送请求(使用代理的方式)
self.cnnt=[NSURLConnection connectionWithRequest:request delegate:self];
// [self.cnnt start];
}
}
#pragma mark- NSURLConnectionDataDelegate代理方法
/*
*当接收到服务器的响应(连通了服务器)时会调用
*/
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
#warning 判断是否是第一次连接
if (self.sumLength) return;
//1.创建文件存数路径
NSString *caches=[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
NSString *filePath=[caches stringByAppendingPathComponent:@"video.zip"];
//2.创建一个空的文件,到沙盒中
NSFileManager *mgr=[NSFileManager defaultManager];
//刚创建完毕的大小是o字节
[mgr createFileAtPath:filePath contents:nil attributes:nil];
//3.创建写数据的文件句柄
self.writeHandle=[NSFileHandle fileHandleForWritingAtPath:filePath];
//4.获取完整的文件长度
self.sumLength=response.expectedContentLength;
}
/*
*当接收到服务器的数据时会调用(可能会被调用多次,每次只传递部分数据)
*/
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
//累加接收到的数据长度
self.currentLength+=data.length;
//计算进度值
double progress=(double)self.currentLength/self.sumLength;
self.progress.progress=progress;
//一点一点接收数据。
NSLog(@"接收到服务器的数据!---%d",data.length);
//把data写入到创建的空文件中,但是不能使用writeTofile(会覆盖)
//移动到文件的尾部
[self.writeHandle seekToEndOfFile];
//从当前移动的位置,写入数据
[self.writeHandle writeData:data];
}
/*
*当服务器的数据加载完毕时就会调用
*/
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(@"下载完毕----%lld",self.sumLength);
//关闭连接,不再输入数据在文件中
[self.writeHandle closeFile];
self.writeHandle=nil;
//清空进度值
self.currentLength=0;
self.sumLength=0;
//设置按钮文字为“已经下载完成”
[self.btn setTitle:@"已经下载完成" forState:UIControlStateNormal];
[self.btn setEnabled:NO];
}
/*
*请求错误(失败)的时候调用(请求超时\断网\没有网\,一般指客户端错误)
*/
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
}
@end
注意:关键代码
从self.currentLength字节部分重新开始读取
NSString *value=[NSString stringWithFormat:@"bytes=%lld-",self.currentLength];
[request setValue:value forHTTPHeaderField:@"Range"];
模拟器运行情况:
程序启动界面:
点击下载按钮后,开始下载文件,此时按钮的提示文字变为暂停。
下载暂停后,点击下载按钮,继续之前的下载。
下载完成后界面效果:
下载完成后,查看项目沙盒: