码迷,mamicode.com
首页 > 移动开发 > 详细

iOS 支持多任务、断点下载(图片、音频、视频) (Demo 一)

时间:2015-08-07 20:00:37      阅读:181      评论:0      收藏:0      [点我收藏+]

标签:ios

具体使用请到我的GitHub
代码: https://github.com/HHuiHao/HSDownloadManager

功能演示:

技术分享

—————–代码实现—————–

开启任务下载资源方法,新开线程并执行下载任务

- (void)download:(NSString *)url progress:(void (^)(NSInteger, NSInteger, CGFloat))progressBlock state:(void (^)(DownloadState))stateBlock
{
    // 验证
    if (!url) return;
    if ([self isCompletion:url]) {
        stateBlock(DownloadStateCompleted);
        NSLog(@"----该资源已下载完成");
        return;
    }

    // 暂停
    if ([self.tasks valueForKey:HSFileName(url)]) {
        [self handle:url];

        return;
    }

    // 创建缓存目录文件
    [self createCacheDirectory];

   NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[[NSOperationQueue alloc] init]];

    // 创建流
    NSOutputStream *stream = [NSOutputStream outputStreamToFileAtPath:HSFileFullpath(url) append:YES];

    // 创建请求
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];

    // 设置请求头
    NSString *range = [NSString stringWithFormat:@"bytes=%zd-", HSDownloadLength(url)];
    [request setValue:range forHTTPHeaderField:@"Range"];

    // 创建一个Data任务
    NSURLSessionDataTask *task = [session dataTaskWithRequest:request];
    NSUInteger taskIdentifier = arc4random() % ((arc4random() % 10000 + arc4random() % 10000));
    [task setValue:@(taskIdentifier) forKeyPath:@"taskIdentifier"];

    // 保存任务
    [self.tasks setValue:task forKey:HSFileName(url)];

    HSSessionModel *sessionModel = [[HSSessionModel alloc] init];
    sessionModel.url = url;
    sessionModel.progressBlock = progressBlock;
    sessionModel.stateBlock = stateBlock;
    sessionModel.stream = stream;
    [self.sessionModels setValue:sessionModel forKey:@(task.taskIdentifier).stringValue];

    [self start:url];
}

分解方法:

  • 验证信息
    if (!url) return;
    if ([self isCompletion:url]) {
        stateBlock(DownloadStateCompleted);
        NSLog(@"----该资源已下载完成");
        return;
    }

    // 暂停
    if ([self.tasks valueForKey:HSFileName(url)]) {
        [self handle:url];

        return;
    }
  • 网络请求实现:NSURLSession
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[[NSOperationQueue alloc] init]];
  • 接收data流:NSOutputStream
NSOutputStream *stream = [NSOutputStream outputStreamToFileAtPath:HSFileFullpath(url) append:YES];
  • 创建请求并设置请求头信息
// 创建请求
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:url]];

// 设置请求头
NSString *range = [NSString stringWithFormat:@"bytes=%zd-", HSDownloadLength(url)];
[request setValue:range forHTTPHeaderField:@"Range"];
  • 并创建一个data任务:NSURLSessionDataTask
NSURLSessionDataTask *task = [session dataTaskWithRequest:request];
NSUInteger taskIdentifier = arc4random() % ((arc4random() % 10000 + arc4random() % 10000));
[task setValue:@(taskIdentifier) forKeyPath:@"taskIdentifier"];
  • 保存每个NSURLSessionDataTask任务:self.tasks
[self.tasks setValue:task forKey:HSFileName(url)];
  • 相关请求信息回调方法封装到model: HSSessionModel
```objc
HSSessionModel *sessionModel = [[HSSessionModel alloc] init];
sessionModel.url = url;
sessionModel.progressBlock = progressBlock;
sessionModel.stateBlock = stateBlock;
sessionModel.stream = stream;
[self.sessionModels setValue:sessionModel forKey:@(task.taskIdentifier).stringValue];

[self start:url];

接收处理数据 NSURLSessionDataDelegate

接收数据

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSHTTPURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler
{

    HSSessionModel *sessionModel = [self getSessionModel:dataTask.taskIdentifier];

    // 打开流
    [sessionModel.stream open];

    // 获得服务器这次请求 返回数据的总长度
    NSInteger totalLength = [response.allHeaderFields[@"Content-Length"] integerValue] + HSDownloadLength(sessionModel.url);
    sessionModel.totalLength = totalLength;

    // 存储总长度
    NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithContentsOfFile:HSTotalLengthFullpath];
    if (dict == nil) dict = [NSMutableDictionary dictionary];
    dict[HSFileName(sessionModel.url)] = @(totalLength);
    [dict writeToFile:HSTotalLengthFullpath atomically:YES];

    // 接收这个请求,允许接收服务器的数据
    completionHandler(NSURLSessionResponseAllow);
}

接收到服务器返回的数据

- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data
{
    // 获取模型
    HSSessionModel *sessionModel = [self getSessionModel:dataTask.taskIdentifier];

    // 写入数据
    [sessionModel.stream write:data.bytes maxLength:data.length];

    // 下载进度
    NSUInteger receivedSize = HSDownloadLength(sessionModel.url);
    NSUInteger expectedSize = sessionModel.totalLength;
    CGFloat progress = 1.0 * receivedSize / expectedSize;

    // block回调
    sessionModel.progressBlock(receivedSize, expectedSize, progress);
}

请求完毕(成功或失败)

- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
{
    HSSessionModel *sessionModel = [self getSessionModel:task.taskIdentifier];
    if (!sessionModel) return;

    if ([self isCompletion:sessionModel.url]) {
        // 下载完成
        sessionModel.stateBlock(DownloadStateCompleted);
    } else if (error){
        // 下载失败
        sessionModel.stateBlock(DownloadStateFailed);
    }

    // 关闭流
    [sessionModel.stream close];
    sessionModel.stream = nil;

    // 清除任务
    [self.tasks removeObjectForKey:HSFileName(sessionModel.url)];
    [self.sessionModels removeObjectForKey:@(task.taskIdentifier).stringValue];
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

iOS 支持多任务、断点下载(图片、音频、视频) (Demo 一)

标签:ios

原文地址:http://blog.csdn.net/alincexiaohao/article/details/47342261

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