NSURLSession-下载图片和视频

iOS的info.plist文件配置

13294749-03d5abbedc05105b.png

一.使用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

猜你喜欢

转载自blog.csdn.net/weixin_33713350/article/details/90909367
0条评论
添加一条新回复