美文网首页
NSURLSession-下载图片和视频

NSURLSession-下载图片和视频

作者: 小石头呢 | 来源:发表于2019-06-05 08:27 被阅读0次

    iOS的info.plist文件配置

    一.使用DataTask下载

    #import "ViewController.h"
    
    @interface ViewController ()<NSURLSessionDataDelegate>
    
    /**接受信息*/
    @property (nonatomic,strong) NSMutableData *mData;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        //1.url
        NSURL *url = [NSURL URLWithString:@"http://b.hiphotos.baidu.com/image/h%3D300/sign=77d1cd475d43fbf2da2ca023807fca1e/9825bc315c6034a8ef5250cec5134954082376c9.jpg"];
        
        //2.request
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        
        //3.NSURLSession
        NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
        NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]];
        
        //创建task
        NSURLSessionDataTask *task = [session dataTaskWithRequest:request];
        
        //开始下载
        [task resume];
    }
    
    //接收到服务器响应
    -(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler{
        //接收到响应信息
        self.mData = [NSMutableData data];
        
        //和urlConnection不同点在于
        //接收到响应信息之后 是否需要继续下载 必须自己配置
        //告诉服务器继续传递数据 NSURLSessionResponseAllow
        completionHandler(NSURLSessionResponseAllow);
    }
    
    //接收到服务器返回数据
    - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data{
        
        //追加信息
        [_mData appendData:data];
    }
    
    //请求完成
    - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{
        
        //解析服务器返回的数据
        NSLog(@"%@", [UIImage imageWithData:_mData]);
    }
    
    @end
    

    二.使用DownloadTask下载

    优势:
    1.可以实现一边下载一边保存
    2.不受苹果后台设置的时间的限制,可以在程序退到后台后继续session中未完成的task,直到全部完成退出后台
    3.在服务器满足苹果API要求的情况下,让断点续传摆脱bytes=%llu-,更简单易用

    2.1.NSURLSessionDownloadTask之block下载

    //url
    NSURL *url = [NSURL URLWithString:@"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1555431276825&di=f6de13e3bae100df9f2be9b14e305df4&imgtype=0&src=http%3A%2F%2Fuploads.5068.com%2Fallimg%2F1801%2F160I4E61-7.jpg"];
        
    
    //创建会话对象
    NSURLSession *session = [NSURLSession sharedSession];
        
    //创建task
    NSURLSessionDownloadTask *task = [session downloadTaskWithURL:url completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
            
           //获取保存文件的路径
           NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"1.png"];
            
           //将url对应的文件copy到指定的路径
           [[NSFileManager defaultManager] moveItemAtURL:location toURL:[NSURL fileURLWithPath:path] error:nil];
            
    }];
        
    //执行task
    [task resume];
    

    Block下载方式不适合大文件下载,因为该方法需要等到文件下载完毕了,才会回调completionHandler后面的block参数,然后才可以在这个block参数可以获取location(文件下载缓存的路径)、response(响应)、error(错误信息)。这样的话,对于大文件,我们就无法实时的在下载过程中获取文件的下载进度了。

    2.2.NSURLSessionDownloadTask之代理方法下载

    #import "ViewController.h"
    
    @interface ViewController ()<NSURLSessionDownloadDelegate>
    
    /**全局化的task*/
    @property (nonatomic,strong) NSURLSessionDownloadTask *task;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        
    }
    
    -(void)viewDidAppear:(BOOL)animated{
        [super viewDidAppear:animated];
        
        //url
        NSURL *url = [NSURL URLWithString:@"https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1555431276825&di=f6de13e3bae100df9f2be9b14e305df4&imgtype=0&src=http%3A%2F%2Fuploads.5068.com%2Fallimg%2F1801%2F160I4E61-7.jpg"];
       
        //默认的congig
        NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
    
        //session
        NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    
        //task
        self.task = [session downloadTaskWithURL:url];
    
        //启动下载任务
        [_task resume];
        
    }
    
    -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
        //running  正在下载
        //suspend  暂停下载
        //complete 下载完成
        //cancel   取消下载
        
        if (_task.state == NSURLSessionTaskStateRunning) {
            
            //由开始状态变成暂停
            [_task suspend];
        }else if(_task.state == NSURLSessionTaskStateSuspended){
            
            //由暂停状态变成开始
            [_task resume];
        }
    }
    
    #pragma mark -------代理方法 ---------
    //边下载边存储->磁盘->手机的内存->程序的沙盒里面->
    //Documents(文件操作) Library(cache缓存) tmp(临时目录)
    //将默认下载的数据从url的path移动(copy,move)到自己的位置
    //当执行完毕,这个临时文件就会被立刻销毁
    - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location{
        
        NSLog(@"%@",location);
        
        //获取保存文件的路径
        NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject stringByAppendingPathComponent:@"1.png"];
        
        NSLog(@"%@",path);
        
        //将url对应的文件copy到指定的路径
        [[NSFileManager defaultManager] moveItemAtURL:location toURL:[NSURL fileURLWithPath:path] error:nil];
        
        NSLog(@"下载完成");
    }
    
    //获取每次下载的长度
    - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{
        
        CGFloat progress = totalBytesWritten*1.0/totalBytesExpectedToWrite;
        
        NSLog(@"%f",progress);
    }
    
    //下载完成,成功出错都会来到这里
    -(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{
        
        NSLog(@"%@",error.userInfo);
    }
    
    @end
    

    代理方法

    - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
    location:默认下载的文件存放的位置
    - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
    session:当前会话  
    downloadTask:当前会话任务  
    bytesWritten:本次写入数据大小  
    totalBytesWritten:已经写入数据大小  totalBytesExpectedToWrite:要下载的文件总大小
    -(void)URLSession:(NSURLSession *)session downloadTask:(nonnull NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes
    恢复下载时调用的代理方法
    -(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
    下载完成时调用的代理方法

    利用DataTask和NSFileHandle实现边下载边保存

    #import "ViewController.h"
    
    @interface ViewController ()<NSURLSessionDataDelegate>
    
    /**文件句柄*/
    @property (nonatomic,strong) NSFileHandle *fileHandle;
    
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        //url
        NSURL *url = [NSURL URLWithString:@"http://b.hiphotos.baidu.com/image/h%3D300/sign=77d1cd475d43fbf2da2ca023807fca1e/9825bc315c6034a8ef5250cec5134954082376c9.jpg"];
        
        //session
        NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
        
        //dataTask
        NSURLSessionDataTask *task = [session dataTaskWithURL:url];
        
        //启动任务
        [task resume];
    }
    
    #pragma mark -------代理方法 ---------
    -(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler{
        
        //为下载做好准备
        
        //1.获取文件路径
        //cache tmp
        NSString *filePath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).lastObject stringByAppendingPathComponent:@"2.png"];
        
        //2.创建文件 用于接受数据
        [[NSFileManager defaultManager] createFileAtPath:filePath contents:nil attributes:nil];
        
        //3.以写的方式创建文件句柄 防止上一次的内容被这一次的内容覆盖
        self.fileHandle = [NSFileHandle fileHandleForWritingAtPath:filePath];
        
        //接受响应后是否下载
        completionHandler(NSURLSessionResponseAllow);
    }
    
    -(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data{
        
        //接受下载的数据
        [_fileHandle writeData:data];
    }
    
    
    -(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{
        
        //对结果进行处理
        [_fileHandle closeFile];
    }
    
    @end
    

    NSOutputStream-保存网络资源到本地
    参考文章:https://www.cnblogs.com/hbf369/p/3581986.html

    2.3.NSURLSessionDownloadTask之后台下载

    步骤:
    1.创建request
    2.配置允许后台任务的session
    3.创建downloadTask
    4.服从NSURLSessionDownloadDelegate
    5.AppDelegate 监听handleEventsForBackgroundURLSession将handle传递给下载类
    6.URLSessionDidFinishEventsForBackgroundURLSession后台下载执行这个方法
    7.didFinishDownloadingToURL将临时文件保存到对应位置

    //AppDelegate关联session,传递block
    -(void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)(void))completionHandler{
        
        //1.将前台的session和后台的session做一个关联
        
        //找到正常接收代理的对象
        ViewController *vc = (ViewController *)self.window.rootViewController;
        
        NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"config"] delegate:vc delegateQueue:[NSOperationQueue mainQueue]];
        
        //将completionHandler传递给执行的对象,让其知道我的下载状态
        vc.completeHandleBlock = completionHandler;
    }
    
    //执行者监听后台是否下载完毕
    -(void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session{
        
        NSLog(@"后台任务下载完毕");
        self.completeHandleBlock();
    }
    

    参考文章:https://www.jianshu.com/p/1211cf99dfc3

    2.4.NSURLSessionDownloadTask代理方法实现断点续传下载

    参考文章:http://www.cnblogs.com/goodboy-heyang/p/5195806.html

    demo链接
    链接:https://pan.baidu.com/s/1Yfa9q9EiWd904LOeQ6z8cQ 密码:tfn8
    链接:https://pan.baidu.com/s/1BqMiH0Cza88eGBU1GX4d-g 密码:6ipc
    链接:https://pan.baidu.com/s/18t4pCZiOkBdyxdzaoilIYg 密码:pg5e
    链接:https://pan.baidu.com/s/18uXCNmU50VTS8B6OjnYOFA 密码:fad4

    相关文章

      网友评论

          本文标题:NSURLSession-下载图片和视频

          本文链接:https://www.haomeiwen.com/subject/ywihzqtx.html