码迷,mamicode.com
首页 > 编程语言 > 详细

多线程--多线程断点下载

时间:2015-09-13 17:18:33      阅读:253      评论:0      收藏:0      [点我收藏+]

标签:

---恢复内容开始---

//
//  HMFileMultiDownloader.m
//  08-多线程断点下载
//
//  Created by apple on 14-6-27.
//  Copyright (c) 2014年 heima. All rights reserved.
//

#import "HMFileMultiDownloader.h"
#import "HMFileSingleDownloader.h"

#define HMMaxDownloadCount 4

@interface HMFileMultiDownloader()
@property (nonatomic, strong) NSMutableArray *singleDownloaders;
@property (nonatomic, assign) long long totalLength;
@end

@implementation HMFileMultiDownloader

- (void)getFilesize
{
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:self.url]];
    request.HTTPMethod = @"HEAD";
    
    NSURLResponse *response = nil;
#warning 这里要用异步请求
    [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil];
    self.totalLength = response.expectedContentLength;
}

- (NSMutableArray *)singleDownloaders
{
    if (!_singleDownloaders) {
        _singleDownloaders = [NSMutableArray array];
        
        // 获得文件大小
        [self getFilesize];
        
        // 每条路径的下载量
        long long size = 0;
        if (self.totalLength % HMMaxDownloadCount == 0) {
            size = self.totalLength / HMMaxDownloadCount;
        } else {
            size = self.totalLength / HMMaxDownloadCount + 1;
        }
        
        // 创建N个下载器
        for (int i = 0; i<HMMaxDownloadCount; i++) {
            HMFileSingleDownloader *singleDownloader = [[HMFileSingleDownloader alloc] init];
            singleDownloader.url = self.url;
            singleDownloader.destPath = self.destPath;
            singleDownloader.begin = i * size;
            singleDownloader.end = singleDownloader.begin + size - 1;
            singleDownloader.progressHandler = ^(double progress){
                NSLog(@"%d --- %f", i, progress);
            };
            [_singleDownloaders addObject:singleDownloader];
        }
        
        // 创建一个跟服务器文件等大小的临时文件
        [[NSFileManager defaultManager] createFileAtPath:self.destPath contents:nil attributes:nil];
        
        // 让self.destPath文件的长度是self.totalLengt
        NSFileHandle *handle = [NSFileHandle fileHandleForWritingAtPath:self.destPath];
        [handle truncateFileAtOffset:self.totalLength];
    }
    return _singleDownloaders;
}

/**
 * 开始(恢复)下载
 */
- (void)start
{
    [self.singleDownloaders makeObjectsPerformSelector:@selector(start)];
    
    _downloading = YES;
}

/**
 * 暂停下载
 */
- (void)pause
{
    [self.singleDownloaders makeObjectsPerformSelector:@selector(pause)];
    _downloading = NO;
}

@end
//
//  HMFileSingleDownloader.h
//  08-多线程断点下载
//
//  Created by apple on 14-6-27.
//  Copyright (c) 2014年 heima. All rights reserved.
//

#import "HMFileDownloader.h"

@interface HMFileSingleDownloader : HMFileDownloader
/**
 *  开始的位置
 */
@property (nonatomic, assign) long long begin;
/**
 *  结束的位置
 */
@property (nonatomic, assign) long long end; 
@end




//
//  HMFileSingleDownloader.m
//  08-多线程断点下载
//
//  Created by apple on 14-6-27.
//  Copyright (c) 2014年 heima. All rights reserved.
//

#import "HMFileSingleDownloader.h"
@interface HMFileSingleDownloader() <NSURLConnectionDataDelegate>
/**
 * 连接对象
 */
@property (nonatomic, strong) NSURLConnection *conn;

/**
 *  写数据的文件句柄
 */
@property (nonatomic, strong) NSFileHandle *writeHandle;
/**
 *  当前已下载数据的长度
 */
@property (nonatomic, assign) long long currentLength;
@end

@implementation HMFileSingleDownloader

- (NSFileHandle *)writeHandle
{
    if (!_writeHandle) {
        _writeHandle = [NSFileHandle fileHandleForWritingAtPath:self.destPath];
    }
    return _writeHandle;
}

/**
 * 开始(恢复)下载
 */
- (void)start
{
    NSURL *url = [NSURL URLWithString:self.url];
    // 默认就是GET请求
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    // 设置请求头信息
    NSString *value = [NSString stringWithFormat:@"bytes=%lld-%lld", self.begin + self.currentLength, self.end];
    [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
{
    
}

/**
 *  2. 当接受到服务器的数据就会调用(可能会被调用多次, 每次调用只会传递部分数据)
 */
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    // 移动到文件的尾部
    [self.writeHandle seekToFileOffset:self.begin + self.currentLength];
    // 从当前移动的位置(文件尾部)开始写入数据
    [self.writeHandle writeData:data];
    
    // 累加长度
    self.currentLength += data.length;
    
    // 打印下载进度
    double progress = (double)self.currentLength / (self.end - self.begin);
    if (self.progressHandler) {
        self.progressHandler(progress);
    }
}

/**
 *  3. 当服务器的数据接受完毕后就会调用
 */
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    // 清空属性值
    self.currentLength = 0;
    
    // 关闭连接(不再输入数据到文件中)
    [self.writeHandle closeFile];
    self.writeHandle = nil;
}

/**
 *  请求错误(失败)的时候调用(请求超时\断网\没有网, 一般指客户端错误)
 */
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    
}

@end
//
//  HMFileDownloader.h
//  08-多线程断点下载
//
//  Created by apple on 14-6-27.
//  Copyright (c) 2014年 heima. All rights reserved.
//

#import <Foundation/Foundation.h>

@interface HMFileDownloader : NSObject
{
    BOOL _downloading;
}
/**
 * 所需要下载文件的远程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);

/**
 * 开始(恢复)下载
 */
- (void)start;

/**
 * 暂停下载
 */
- (void)pause;
@end

 

 

//
//  HMViewController.m
//  08-多线程断点下载
//
//  Created by apple on 14-6-27.
//  Copyright (c) 2014年 heima. All rights reserved.
//

#import "HMViewController.h"
#import "HMFileMultiDownloader.h"

@interface HMViewController ()
@property (nonatomic, strong) HMFileMultiDownloader *fileMultiDownloader;
@end

@implementation HMViewController
-  (HMFileMultiDownloader *)fileMultiDownloader
{
    if (!_fileMultiDownloader) {
        _fileMultiDownloader = [[HMFileMultiDownloader alloc] init];
        // 需要下载的文件远程URL
        _fileMultiDownloader.url = @"http://192.168.1.200:8080/MJServer/resources/jre.zip";
        // 文件保存到什么地方
        NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
        NSString *filepath = [caches stringByAppendingPathComponent:@"jre.zip"];
        _fileMultiDownloader.destPath = filepath;
    }
    return _fileMultiDownloader;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    [self.fileMultiDownloader start];
}

@end

 

---恢复内容结束---

多线程--多线程断点下载

标签:

原文地址:http://www.cnblogs.com/chen495353880/p/4805168.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!