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

具体使用请到我的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];
}

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

时间: 2024-08-25 03:32:01

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

iOS 大文件断点下载

iOS 在下载大文件的时候,可能会因为网络或者人为等原因,使得下载中断,那么如何能够进行断点下载呢? // resumeData的文件路径 #define XMGResumeDataFile [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"resumeData.tmp"] #import

iOS网络-文件下载,断点下载,输出流下载

小文件下载 NSURLConnection-delegate实现,可以监听到下载的进度,但是还是无法解决内存飙升的问题,所以仅限小文件下载 1 @interface ViewController ()<NSURLConnectionDataDelegate> 2 @property (weak, nonatomic) IBOutlet UIProgressView *progressView; 3 /** 接收数据的data */ 4 @property (nonatomic, strong)

iOS开发总结 - 下载图片并浏览(UICollectionView)

昨天根据贴图库api做的一个浏览图片的Demo, 源码在这: https://github.com/beddup/TieTuKuBrowers 总结如下: 1. AFNetworking 的使用 demo中通过http api 下载数据,数据有json和image,所以使用了AFHTTPSessionManager (基于NSURLSession) AFNetworking非常方便,可以直接将json转换为NSArray/ NSDictionary, 将image data转换为 UIImage

iOS WKWebView 退出后停止播放音频/视频

1.注入使网页停止音频.视频播放的JS代码(Swift 4): 1 let pauseJSString:String = 2 """ 3 var videos = document.getElementsByTagName("video"); 4 function pauseVideo(){ 5 var len = videos.length 6 for(var i=0;i<len;i++){ 7 videos[i].pause(); 8 } 9 }

流式存储音频/视频

流式存储音频/视频 1.1.下载文件的传统方法: 传统的浏览器从服务器下载音频/视频文件: ① 用户从客户机(client machine)的浏览器上用 HTTP 协议向服务器请求下载某个音频/视频文件. ② 服务器如有此文件就发送给浏览器.在响应报文中就装有用户所要的音频/视频文件.整个下载过程可能会花费很长的时间. ③ 当浏览器完全收下这个文件后,就可以传送给自己机器上的媒体播放器进行解压缩,然后播放. 1.2.具有元文件的万维网服务器 元文件就是一种非常小的文件,它描述或指明其他文件的一些

ios开发视频播放后台下载功能实现 :1,ios播放视频 ,包含基于AVPlayer播放器,2,实现下载,iOS后台下载(多任务同时下载,单任务下载,下载进度,下载百分比,文件大小,下载状态)(真机调试功能正常)

ABBPlayerKit ios开发视频播放后台下载功能实现 : 代码下载地址:https://github.com/niexiaobo/ABBPlayerKit github资料学习和下载地址:https://github.com/niexiaobo/ 实现功能 :播放视频 ,视频后台下载 (真机调试功能正常) 1.使用ZFPlayer播放视频(可以在线和本地播放,基于AVPlayer,调节音量和屏幕亮度) 2.使用 WHCNetWorkKit 实现下载,后台下载(多任务同时下载,单任务下载,

android 单线程多任务断点排队下载(支持多界面刷新)

最近在做一个单线程多任务的断点排队下载的功能,网上确实有很多这样的demo.但是呢我发现大部分网上的demo都是很些不完整的要么就是有缺陷的,可能是我还没找到.今天我给大家带来的一个功能完整的并且可以多界面刷新,就比如:我当前界面点了下载放后台下载了,退出了当前界面在进来网上很多这样demo都没做继续更新界面.并且还做了排队. 首先我们先制定下计划: 1.我们做的是断点下载,断点下载肯定是需要记录当前下载的进度和文件总大小的.这个当然是放在数据库里面最好,当然肯定会是异步来操作数据库,这里我们就

iOS 音频视频制作

--iOS多媒体 概览 随着移动互联网的发展,如今的手机早已不是打电话.发短信那么简单了,播放音乐.视频.录音.拍照等都是很常用的功能.在iOS中对于多媒体的支持是非常强大的,无论是音视频播放.录制,还是对麦克风.摄像头的操作都提供了多套API.在今天的文章中将会对这些内容进行一一介绍: 音频 音效 音乐 音频会话 录音 音频队列服务 视频 MPMoviePlayerController MPMoviePlayerViewController AVPlayer 摄像头 UIImagePicker

iOS开发网络请求——大文件的多线程断点下载

iOS开发中网络请求技术已经是移动app必备技术,而网络中文件传输就是其中重点了.网络文件传输对移动客户端而言主要分为文件的上传和下载.作为开发者从技术角度会将文件分为小文件和大文件.小文件因为文件大小比较小导致传输所需时间少传输就快,因此不太容易影响用户体验,可用的技术就多.而大文件因为文件大小比较大导致传输时间长,因此就需要考虑到各种用户体验,比如避免在上传下载文件过程中阻塞主线程影响用户体验,就需要使用到多线程技术:为了给用户友好的进度提示,因此又需要开发中跟踪数据上传和下载数据的变化:为