iOS 下载功能:断点下载(暂停和开始)(NSURLConnectionDataDelegate方法)

1,model文件代码

文件名称:HMFileDownloader.h

 

#import <Foundation/Foundation.h>

 

@interface HMFileDownloader : NSObject

/**

 * 所需要下载文件的远程URL(连接服务器的路径)

 */

@property (nonatomic, copy) NSString *url;

/**

 * 文件的存储路径(文件下载到什么地方)

 */

@property (nonatomic, copy) NSString *destPath;

 

/**

 * 是否正在下载(有没有在下载, 只有下载器内部才知道)

 */

@property (nonatomic, readonly, getter = isDownloading) BOOL downloading;

 

/**

 * 用来监听下载进度

 */

@property (nonatomic, copy) void (^progressHandler)(double progress);

/**

 * 用来监听下载完毕

 */

@property (nonatomic, copy) void (^completionHandler)();

/**

 * 用来监听下载失败

 */

@property (nonatomic, copy) void (^failureHandler)(NSError *error);

 

/**

 * 开始(恢复)下载

 */

- (void)start;

 

/**

 * 暂停下载

 */

- (void)pause;

 

@end

文件名称:HMFileDownloader.m

 

#import "HMFileDownloader.h"

 

@interface HMFileDownloader() <NSURLConnectionDataDelegate>

/**

 * 连接对象

 */

@property (nonatomic, strong) NSURLConnection *conn;

 

/**

 *  写数据的文件句柄

 */

@property (nonatomic, strong) NSFileHandle *writeHandle;

/**

 *  当前已下载数据的长度

 */

@property (nonatomic, assign) long long currentLength;

/**

 *  完整文件的总长度

 */

@property (nonatomic, assign) long long totalLength;

@end

 

@implementation HMFileDownloader

 

/**

 * 开始(恢复)下载

 */

- (void)start

{

    NSURL *url = [NSURL URLWithString:self.url];

    // 默认就是GET请求

    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];

    // 设置请求头信息

    NSString *value = [NSString stringWithFormat:@"bytes=%lld-", self.currentLength];

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

    self.conn = [NSURLConnection connectionWithRequest:request delegate:self];

    

    _downloading = YES;

}

 

/**

 * 暂停下载

 */

- (void)pause

{

    [self.conn cancel];

    self.conn = nil;

    

    _downloading = NO;

}

 

#pragma mark - NSURLConnectionDataDelegate 代理方法

/**

 *  1. 当接受到服务器的响应(连通了服务器)就会调用

 */

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

{

#warning 一定要判断

    if (self.totalLength) return;

    

    // 1.创建一个空的文件到沙盒中

    NSFileManager *mgr = [NSFileManager defaultManager];

    // 刚创建完毕的大小是0字节

    [mgr createFileAtPath:self.destPath contents:nil attributes:nil];

    

    // 2.创建写数据的文件句柄

    self.writeHandle = [NSFileHandle fileHandleForWritingAtPath:self.destPath];

    

    // 3.获得完整文件的长度

    self.totalLength = response.expectedContentLength;

}

 

/**

 *  2. 当接受到服务器的数据就会调用(可能会被调用多次, 每次调用只会传递部分数据)

 */

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

{

    // 累加长度

    self.currentLength += data.length;

    NSLog(@"=%lld==",self.currentLength);

 

    // 显示进度

    double progress = (double)self.currentLength / self.totalLength;

    if (self.progressHandler) { // 传递进度值给block

        self.progressHandler(progress);

    }

    

    // 移动到文件的尾部

    [self.writeHandle seekToEndOfFile];

    // 从当前移动的位置(文件尾部)开始写入数据

    [self.writeHandle writeData:data];

}

 

/**

 *  3. 当服务器的数据接受完毕后就会调用

 */

- (void)connectionDidFinishLoading:(NSURLConnection *)connection

{

    // 清空属性值

    self.currentLength = 0;

    self.totalLength = 0;

    

    if (self.currentLength == self.totalLength) {

        // 关闭连接(不再输入数据到文件中)

        [self.writeHandle closeFile];

        self.writeHandle = nil;

    }

    

    if (self.completionHandler) {

        self.completionHandler();

    }

}

 

/**

 *  请求错误(失败)的时候调用(请求超时\断网\没有网, 一般指客户端错误)

 */

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error

{

    if (self.failureHandler) {

        self.failureHandler(error);

    }

}

 

@end

 

 

2、将上述两个文件拖到工程中

3、在控制器文件中导入

#import "HMFileDownloader.h"

声明

@property (nonatomic, strong)NSString  *url;

@property (retain, nonatomic)  UIProgressView *progressView;

@property (nonatomic, strong) HMFileDownloader *fileDownloader;

 

- (void)viewDidLoad

{

 _progressView=[[UIProgressView alloc]init];

    _progressView.frame=CGRectMake(10, 150, 170, 20);

    

    [self.view addSubview:_progressView];

 

[self fileDownloader];

}

- (void)fileDownloader

{

 

    if (!_ViewCont.fileDownloader) {

        _fileDownloader = [[HMFileDownloader alloc] init];

        // 需要下载的文件远程URL

        _fileDownloader.url = @"http://192.168.1.9:8080/wyhouAppServices/upload/app_user/iOS%207%20Cookbook.pdf";

        // 文件保存到什么地方1

        NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];

        NSString *filepath = [caches stringByAppendingPathComponent:@"20Cookbook.pdf"];

        

        

        // 文件保存到什么地方2

        NSURL *targetURL = [NSURL URLWithString:_ViewCont.fileDownloader.url];

        NSString *docPath = [self documentsDirectoryPath];

        // Combine the filename and the path to the documents dir into the full path

        NSString *pathToDownloadTo = [NSString stringWithFormat:@"%@/%@", docPath, [targetURL lastPathComponent]];

        

        

        

        _fileDownloader.destPath = pathToDownloadTo;

        //        typeof(10) a = 20; // int a = 20;

        

        __weak typeof(self) vc = self;

        _fileDownloader.progressHandler = ^(double progress) {

            vc.progressView.progress=progress;

//            _progressView.progress = progress;

        };

        

        _fileDownloader.completionHandler = ^{

            NSLog(@"------下载完毕");

        };

        

        _fileDownloader.failureHandler = ^(NSError *error){

            

        };

    }else{

       _progressView.progress= _ViewCont.progressView.progress;

         __weak typeof(self) vc = self;

        _fileDownloader.progressHandler = ^(double progress) {

            vc.progressView.progress=progress;

            //

            

        

        };

    NSLog(@"------");

    

    }

//    return _fileDownloader;

}

-(void)dealloc{

    _progressView.progress=_progressView.progress;

 

}

 

// 按钮文字: "开始", "暂停"

- (void)start { // self.currentLength == 200

    if (_fileDownloader.isDownloading) { // 暂停下载

        [_fileDownloader pause];

        

        [_testBtn setTitle:@"恢复" forState:UIControlStateNormal];

    } else { // 开始下载

        [_fileDownloader start];

        

        [_testBtn setTitle:@"暂停" forState:UIControlStateNormal];

    }

}

posted @ 2015-07-13 12:30  穿山甲随笔-iOS开发  阅读(624)  评论(0编辑  收藏  举报