宽容他人,放过自己。

开发网络篇-文件下载(暂停和恢复)

Posted on By anchoriteFili

一、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"];

模拟器运行情况:

程序启动界面:

012249285745434.png

点击下载按钮后,开始下载文件,此时按钮的提示文字变为暂停。

012250036054703.png

下载暂停后,点击下载按钮,继续之前的下载。

012251491848124.png

下载完成后界面效果:

012252332779728.png

下载完成后,查看项目沙盒:

012253281528926.png