NSHTTPRequest 请求网络,下载性能优化和断点续传


#import <UIKit/UIKit.h>


@interface ViewController : UIViewController


@property (nonatomicstrongNSMutableData *receiveData;

@property (weaknonatomicIBOutlet UIProgressView *progressView;

@property (weaknonatomicIBOutlet UILabel *progressLabel;


@end


//  ViewController.m

//  UIGJ04-02

//

//  Created by imac on 15/9/7.

//  Copyright (c) 2015 imac. All rights reserved.

//


#import "ViewController.h"


/*

 下载性能优化

 使用一个缓冲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. 续传写入文件时,总是从文件末尾追加写入文件

 

 */




@interface ViewController ()<NSURLConnectionDataDelegate>

{

    double totalSize; //下载数据的总大小

    

    double receiveTotal; //接收的数据大小

    

    NSString *_filePath;  //文件存储的路径

    

    BOOL isDownLoad;//标识是否在下载

    

    NSURLConnection *_connection; //网络请求对象


}

@end


@implementation ViewController


- (void)viewDidLoad {

    [super viewDidLoad];

    // Do any additional setup after loading the view, typically from a nib.


    NSLog(@"%@"NSHomeDirectory());

    

    //取得下载数据的大小 userDefaults是一个单例

    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];

    

    receiveTotal = [[userDefaults objectForKey:@"ReceivedTotal"doubleValue];

    totalSize = [[userDefaults objectForKey:@"TotalSize"doubleValue];

    

    //显示上一次下载的进度

    if (totalSize > 0) {

        CGFloat progress = receiveTotal / totalSize;

        self.progressLabel.text = [NSString stringWithFormat:@"%.2f%%", progress * 100];

        self.progressView.progress = progress;

    }


}



- (IBAction)downLoadAction:(UIButton *)sender {

    

    

    if (!isDownLoad) {

        //1 构建URL

        NSURL *url = [NSURL URLWithString:@"http://free2.macx.cn:8182/tools/other4/iStatMenus511b17.dmg"];

        //2 构建Request

        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];

        

        //设置断点续传

        if (receiveTotal > 0) {

            

            //设置继续下载的位置

            NSString *value = [NSString stringWithFormat:@"bytes=%d-",(int)receiveTotal];

            [request setValue:value forHTTPHeaderField:@"Range"];

        }

        

        //3 发送异步请求

         _connection = [NSURLConnection connectionWithRequest:request delegate:self];

        

        isDownLoad = YES;

        

        

        //获取字符串

        NSString *urlStr = url.absoluteString;

        //获取路径的最后一部分

        NSString *fileName = [urlStr lastPathComponent];

        

        //构建文件路径

        _filePath = [NSHomeDirectory() stringByAppendingFormat:@"/Documents/%@",fileName];

        

        //创建文件

        //判断文件是否存在,再创建

        if (![[NSFileManager defaultManagerfileExistsAtPath:_filePath]) {

            [[NSFileManager defaultManagercreateFileAtPath:_filePath contents:nil attributes:nil];

        }

        

    }

    

}


- (IBAction)pauseAction:(UIButton *)sender {

    

    //取消下载

    [_connection cancel];

    _connection = nil;

    

    //将缓冲数据写入文件

    [self appendFileData:self.receiveData];

    

    //本地保存下载文件的大小  总文件的大小  生成的plist文件存放在当前文件路径下Library --  Preferences 

    NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];

    [userDefaults setObject:@(receiveTotal) forKey:@"ReceivedTotal"];

    [userDefaults setObject:@(totalSize) forKey:@"TotalSize"];

    

    //将数据同步写入文件

    [userDefaults synchronize];

    

    isDownLoad = NO;

    

}



#pragma mark -NSURLConnectionDataDelegate

//服务器响应了

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSHTTPURLResponse *)response

{

    self.receiveData = [[NSMutableData allocinit];

    

    

    //判断总大小是否为0,为0,说明是从起始位置开始下载,需要获取总文件的大小

    

    if (totalSize == 0) {

        //获取所有响应头

        NSDictionary *fields = response.allHeaderFields;

        

        //获取数据的总大小

        NSNumber *length = [fields objectForKey:@"Content-Length"];

        

        totalSize = [length doubleValue];

        

        NSLog(@"totalSize is %.2f"totalSize);

    }

    

    



}

//接收数据

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data

{

    

//    NSLog(@"%ld", data.length);


    [self.receiveData appendData:data];

    

    //已接收数据总大小 / 下载文件的总大小  进度

    receiveTotal += data.length;

    double progress = receiveTotal / totalSize;

    

    //当前实在主线程中   刷新UI

    self.progressView.progress = progress;

    self.progressLabel.text = [NSString stringWithFormat:@"%.2f%%", progress * 100];

    

    //判断缓冲的数据大小是否>500kB

    if (self.receiveData.length > 500 * 1000) {

        //往文件路径中写入数据

        [self appendFileData:self.receiveData];

        

        //清空

        [self.receiveData setData:nil];

    }

    

    

}


- (void)appendFileData:(NSData *)data

{

    if (data.length == 0) {

        return;

    }

    

    //使用NSFielHandle写文件,此文件必须已经创建

    NSFileHandle *fileHandle = [NSFileHandle fileHandleForWritingAtPath:_filePath];

    

    //将数据插入到写入点

    [fileHandle seekToEndOfFile];

    [fileHandle writeData:data];

    

    //关闭文件,确保写入完成

    [fileHandle closeFile];

    

}




//数据传输完成

- (void)connectionDidFinishLoading:(NSURLConnection *)connection

{

    //将最后一个缓冲文件数据写入文件

    if (self.receiveData.length < 500 * 1000) {

        [self appendFileData:self.receiveData];

        [self.receiveData setData:nil];

    }

    

    _progressLabel.text = @"下载完成";

    

    isDownLoad = NO;



}




- (void)didReceiveMemoryWarning {

    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.

}


@end


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值