下载器

#import "ViewController.h"

@interface ViewController ()<NSURLSessionTaskDelegate, NSURLSessionDataDelegate>
{
    UITextField *_textfield;
    UIProgressView *_progressView;
    NSURLSession *_session;
    NSURLSessionDataTask *_task;
    NSMutableData *_data;
    NSInteger _sourceSize;
    NSFileHandle *_writeHandle;
    NSString *_api;
}
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.view.backgroundColor = [UIColor grayColor];
    [self creatLayout];
    
//    图片: http://i2.cqnews.net/car/attachement/jpg/site82/20120817/5404a6b61e3c1197fb211d.jpg
//    音乐: http://link.hhtjim.com/163/422104315.mp3
//    视频: http://data.vod.itc.cn/?rb=1&prot=1&key=jbZhEJhlqlUN-Wj_HEI8BjaVqKNFvDrn&prod=flash&pt=1&new=/198/232/8mIXFONKIQNHKlScaM76kB.mp4
    _session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration ephemeralSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
}
#pragma mark 创建布局
- (void)creatLayout {
    _textfield = [UITextField new];
    _textfield.backgroundColor = [UIColor whiteColor];
    _textfield.frame = CGRectMake(50, 150, 300, 50);
    [self.view addSubview:_textfield];
    
    UIButton *startButton = [UIButton buttonWithType:UIButtonTypeSystem];
    startButton.frame = CGRectMake(50, 250, 80, 50);
    [startButton setTintColor:[UIColor whiteColor]];
    startButton.backgroundColor = [UIColor redColor];
    [startButton setTitle:@"开始" forState:UIControlStateNormal];
    [startButton addTarget:self action:@selector(didClicked:) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:startButton];
    
    UIButton *pauseButton = [UIButton buttonWithType:UIButtonTypeSystem];
    pauseButton.frame = CGRectMake(270, 250, 80, 50);
    [pauseButton setTintColor:[UIColor whiteColor]];
    pauseButton.backgroundColor = [UIColor redColor];
    [pauseButton setTitle:@"暂停" forState:UIControlStateNormal];
    [pauseButton addTarget:self action:@selector(didClicked:)forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:pauseButton];
    
    _progressView = [UIProgressView new];
    _progressView.frame = CGRectMake(50, 350, 300, 50);
    [self.view addSubview:_progressView];
}
#pragma mark 点击Button
- (void)didClicked: (UIButton *)sender {
    if ([sender.currentTitle isEqualToString:@"开始"]) {
        _api = _textfield.text;
        NSLog(@"API: %@", _api);
        NSString *targetFileName = [self cacheNameWithURL:_api];
        //缓存文件不存在
        if (![[NSFileManager defaultManager] fileExistsAtPath:targetFileName]) {
            //完整文件存在
            if ([[NSFileManager defaultManager] fileExistsAtPath:[self fileNameWithURL:_api]]) {
                UIAlertController *alertCtl = [UIAlertController alertControllerWithTitle:@"文件已存在" message:@"是否重新下载" preferredStyle:UIAlertControllerStyleAlert];
                UIAlertAction *action1 = [UIAlertAction actionWithTitle:@"是" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
                    //删除文件, 重新创建文件且重新启动任务
                    [[NSFileManager defaultManager] removeItemAtPath:[self fileNameWithURL:_api] error:nil];
                    [[NSFileManager defaultManager] createFileAtPath:targetFileName contents:nil attributes:nil];
                    _writeHandle = [NSFileHandle fileHandleForWritingAtPath:targetFileName];
                    _task = [_session dataTaskWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:_api]]];
                    [_task resume];
                }];
                UIAlertAction *action2 = [UIAlertAction actionWithTitle:@"否" style:UIAlertActionStyleDestructive handler: nil];
                [alertCtl addAction:action2];
                [alertCtl addAction:action1];
                [self presentViewController:alertCtl animated:YES completion:nil];
            }
            //只有缓存文件存在
            else {
                [[NSFileManager defaultManager] createFileAtPath:targetFileName contents:nil attributes:nil];
                _writeHandle = [NSFileHandle fileHandleForWritingAtPath:targetFileName];
                _task = [_session dataTaskWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:_api]]];
                [_task resume];
            }
        }
        //缓存文件存在
        else {
            _writeHandle = [NSFileHandle fileHandleForWritingAtPath:targetFileName];
            [_writeHandle seekToEndOfFile];
            
            //如果暂停
            if (_task.state == NSURLSessionTaskStateSuspended) {
                [_task resume];
                NSLog(@"开始");
            }
            //已经结束, 重新启动任务
            else {
                if (!_api.length) {
                    return;
                }
                NSFileHandle *readHandle = [NSFileHandle fileHandleForReadingAtPath:[self cacheNameWithURL:_api]];
                //获取未完成的缓存文件大小
                NSLog(@"缓存文件大小: %lld", [readHandle seekToEndOfFile]);
                NSMutableURLRequest *mutiRequest= [NSMutableURLRequest requestWithURL:[NSURL URLWithString:_api]];
                //自定义下载范围("bytes=100-":表示下载100以后的所有数据, "bytes=-100":表示下载0~100的数据),Key必须是"Range"
                //注意自己设置过"request"以后,状态码"statusCode"会变成"206"
                [mutiRequest setValue:[NSString stringWithFormat:@"bytes=%lld-", [readHandle seekToEndOfFile]] forHTTPHeaderField:@"Range"];
                _task = [_session dataTaskWithRequest:mutiRequest];
                [_task resume];
            }
        }
    }
    //暂停
    else {
        if (_task.state == NSURLSessionTaskStateRunning) {
            [_task suspend];
            NSLog(@"暂停");
        }
    }
}
#pragma mark 响应
-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler {
    
    NSHTTPURLResponse *resp = (NSHTTPURLResponse *)response;
    _sourceSize = resp.expectedContentLength;
    NSLog(@"%ld", _sourceSize);
    NSLog(@"%@", resp);
    _data = [NSMutableData data];
    _progressView.progress = 0;
    if (resp.statusCode == 200 || resp.statusCode == 206) {
        completionHandler(NSURLSessionResponseAllow);
    }
}
#pragma mark 数据
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data {
    NSLog(@"%ld", data.length);
    [_data appendData:data];
    _progressView.progress = (float)_data.length / _sourceSize;
    [_writeHandle writeData:data];
}
#pragma mark 下载完成
-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
    if (!error) {
        NSLog(@"完成");
        [[NSFileManager defaultManager] moveItemAtPath:[self cacheNameWithURL:_api] toPath:[self fileNameWithURL:_api] error:nil];
    }
    else {
        NSLog(@"error: %@", error);
    }
    [_writeHandle closeFile];
}
#pragma mark 获取文件名
- (NSString *)fileNameWithURL:(NSString *)URLName {
    if (!URLName) {
        return nil;
    }
    NSArray *tempArray = [URLName componentsSeparatedByString:@"/"];
    NSString *tempPath = tempArray.lastObject;
    NSString *fileName = [NSString stringWithFormat:@"%@/%@", @"Users/apple/Desktop", tempPath];
    return fileName;
}
#pragma mark 获取缓存文件名
- (NSString *)cacheNameWithURL:(NSString *)URLName {
    if (!URLName) {
        return nil;
    }
    NSArray *urlArray = [URLName componentsSeparatedByString:@"/"];
    NSString *fileName = urlArray.lastObject;
    NSArray *tempArray = [fileName componentsSeparatedByString:@"."];
    NSString *tempStr = tempArray.firstObject;
    NSString *cacheName = [tempStr stringByAppendingString:@".cache"];
    NSString *cacheFileName = [NSString stringWithFormat:@"%@/%@", @"/Users/apple/Desktop", cacheName];
    return cacheFileName;
}

@end
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,340评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,762评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,329评论 0 329
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,678评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,583评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,995评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,493评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,145评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,293评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,250评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,267评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,973评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,556评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,648评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,873评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,257评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,809评论 2 339

推荐阅读更多精彩内容

  • Python应用现在如火如荼,应用范围很广。因其效率高开发迅速的优势,快速进入编程语言排行榜前几名。本系列文章致力...
    做全栈攻城狮阅读 1,359评论 0 7
  • 先说两句 现在国内国外的很多游戏,特别是网络游戏,在下载的时候往往都不提供真实的下载地址,而是选择提供一个...
    明月喵阅读 4,398评论 0 0
  • 高铁潮汕站——铭星酒店 1,高铁站出来后,往北出站口走去坐专线大巴。澄海线:潮汕站——豪庭大酒店 2,定往澄海方向...
    谢烨生Jason阅读 483评论 0 0
  • 什么是家?每个人有每个人的认知。 一个人的世界无拘无束,自由自在,两个人组成一个家之后为什么两个人都感觉没有以前一...
    月下独酌2阅读 169评论 0 1
  • 偏爱 独饮孤寂苦酒, 邀明月同我方休。 拥挤街头, 唯痴心无缘牵手。 图片发自简书App 薄曦烬红烛, 旧梦...
    轻风逐目阅读 209评论 0 0