NSURLSession的简单

//
//  ViewController.m
//  NSURLSession
//
//  Created by kuyu on 16/3/1.
//  Copyright © 2016年 TCL-YX. All rights reserved.
//

#import "ViewController.h"
#define kImageURL @"http://b.hiphotos.baidu.com/image/pic/item/d788d43f8794a4c274c8110d0bf41bd5ad6e3928.jpg"
#define kDataUrl @"http://api.openweathermap.org/data/2.5/weather?q=London,uk"
@interface ViewController ()<NSURLSessionDataDelegate,NSURLSessionDownloadDelegate>

@property (weak, nonatomic) IBOutlet UIImageView *imageView;

@property (strong,nonatomic) NSMutableData *myData ;

@property (strong,nonatomic) NSURLSessionDownloadTask *downloadTask ;

@property (strong,nonatomic) NSData *resumeData ;
@end

@implementation ViewController

-(NSMutableData *)myData
{
    if (_myData == nil) {
        
        self.myData = [NSMutableData data];
    }
    
    return _myData ;
}

- (void)viewDidLoad {
    [super viewDidLoad];
    
    /*
    URL Session的基本概念
    1>>>.三种工作模式
    
     默认会话模式(default):工作模式类似于原来的NSURLConnection,使用的是基于磁盘缓存的持久化策略,使用用户keychain中保存的证书进行认证授权。
     
     瞬时会话模式(ephemeral):该模式不使用磁盘保存任何数据。所有和会话相关的caches,证书,cookies等都被保存在RAM中,因此当程序使会话无效,这些缓存的数据就会被自动清空。
     
     后台会话模式(background):该模式在后台完成上传和下载,在创建Configuration对象的时候需要提供一个NSString类型的ID用于标识完成工作的后台会话。
     
     
     2>>>.NSURLSession支持的三种任务
     
     NSURLSession类支持三种类型的任务:加载数据,下载和上传。
     
     
     二、相关的类
     
     NSURLConnection这个名字,实际上指的是一组构成Foundation框架中URL加载系统的相互关联的组件:NSURLRequest,NSURLResponse,NSURLProtocol,NSURLCache,NSHTTPCookieStorage,NSURLCredentialStorage,以及和它同名的NSURLConnection。
     
     在WWDC 2013中,Apple的团队对NSURLConnection进行了重构,并推出了NSURLSession作为替代。
     
     NSURLSession也是一组相互依赖的类,它的大部分组件和NSURLConnection中的组件相同如NSURLRequest,NSURLCache等。而NSURLSession的不同之处在于,它将NSURLConnection替换为NSURLSession和NSURLSessionConfiguration,以及3个NSURLSessionTask的子类:NSURLSessionDataTask, NSURLSessionUploadTask, 和NSURLSessionDownloadTask。
     
     
     */
    
    
    /*
    1)使用步骤
    使用NSURLSession创建task,然后执行task
    (2)关于task
    a.NSURLSessionTask是一个抽象类,本身不能使用,只能使用它的子类        
    b.NSURLSessionDataTask\NSURLSessionUploadTask\NSURLSessionDownloadTask

    */
    
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark --GET
- (IBAction)getRequest:(id)sender {
    
    //发送get请求
    //1.创建NSURLSession对象(可以获取单例对象)
    NSURLSession *session = [NSURLSession sharedSession];
    
    //2.根据NSURLSession对象创建一个Task
    NSURL *url = [NSURL URLWithString:kDataUrl];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    
    
    
    //方法参数说明
    /*
     注意:该block是在子线程中调用的,如果拿到数据之后要做一些UI刷新操作,那么需要回到主线程刷新
     第一个参数:需要发送的请求对象
     block:当请求结束拿到服务器响应的数据时调用block
     block-NSData:该请求的响应体
     block-NSURLResponse:存放本次请求的响应信息,响应头,真实类型为NSHTTPURLResponse
     block-NSErroe:请求错误信息
     */
    
   __weak ViewController *mySelf = self ;
    
    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
       
        //拿到响应头信息
        
        NSHTTPURLResponse *response1 = (NSHTTPURLResponse *)response ;
        
        NSLog(@"%@/n%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding],response1.allHeaderFields);
        
        mySelf.imageView.image = [UIImage imageWithData:data];
        
    }];
    
    //3.执行Task
    //注意:刚创建出来的task默认是挂起状态的,需要调用该方法启动任务(执行任务)
    
    [dataTask resume];
    
  
    
/**********************GET的第二种发送请求********************/
    //注意:该方法内部默认会把URL对象包装成一个NSURLRequest对象(默认是GET请求)
    //方法参数说明
    /*
     //第一个参数:发送请求的URL地址
     //block:当请求结束拿到服务器响应的数据时调用block
     //block-NSData:该请求的响应体
     //block-NSURLResponse:存放本次请求的响应信息,响应头,真实类型为NSHTTPURLResponse
     //block-NSErroe:请求错误信息
     */

//    
//    NSURLSessionDataTask *dataTask1 = [session dataTaskWithURL:[NSURL URLWithString:kImageURL] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
//       
//        
//        self.imageView.image = [UIImage imageWithData:data];
//        
//        
//    }];
//    
//    [dataTask1 resume];
    
}


#pragma mark --POST请求
- (IBAction)postRequest:(id)sender {
    
    //1.创建NSURLSession对象(可以获取单例对象)
    NSURLSession *session = [NSURLSession sharedSession];
    
    
    //2.根据NSURLSession对象创建一个Task
    
    NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login"];
    
    //创建一个请求对象,并这是请求方法为POST,把参数放在请求体中传递
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    request.HTTPMethod = @"POST";
    request.HTTPBody = [@"username=520it&pwd=520it&type=JSON" dataUsingEncoding:NSUTF8StringEncoding];
    
    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * __nullable data, NSURLResponse * __nullable response, NSError * __nullable error) {
        //拿到响应头信息
        NSHTTPURLResponse *res = (NSHTTPURLResponse *)response;
        
        //解析拿到的响应数据
        NSLog(@"%@\n%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding],res.allHeaderFields);
    }];
    
    //3.执行Task
    //注意:刚创建出来的task默认是挂起状态的,需要调用该方法来启动任务(执行任务)
    [dataTask resume];
    
}

#pragma mark  --文件上传
- (IBAction)upRequest:(id)sender {
    
    
    //在NSURLSession中,文件上传方式主要有以下两种:
    
    
    //(1)实现文件上传的方法
    
    /*
     第一个参数:请求对象
     第二个参数:请求体(要上传的文件数据)
     block回调:
     NSData:响应体
     NSURLResponse:响应头
     NSError:请求的错误信息
     */
//    NSURLSessionUploadTask *uploadTask =  [[NSURLSession sharedSession] uploadTaskWithRequest:request fromData:data completionHandler:^(NSData * __nullable data, NSURLResponse * __nullable response, NSError * __nullable error)
//    
    
    
    
    
    
    
    
    //(2)设置代理,在代理方法中监听文件上传进度
    /*
     调用该方法上传文件数据
     如果文件数据很大,那么该方法会被调用多次
     参数说明:
     totalBytesSent:已经上传的文件数据的大小
     totalBytesExpectedToSend:文件的总大小
     */
//    -(void)URLSession:(nonnull NSURLSession *)session task:(nonnull NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend
//    {
//        NSLog(@"%.2f",1.0 * totalBytesSent/totalBytesExpectedToSend);
//    }
    
    
    
    
    
    
    
    
    
    
    
    
   /*
    NSURLSessionUploadTask *task =
    [[NSURLSession sharedSession] uploadTaskWithRequest:request
                                               fromFile:fileName
                                      completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
                                      }];
    

    
    [[NSURLSession sharedSession] uploadTaskWithRequest:request
                               fromData:body
                      completionHandler:^(NSData data, NSURLResponse response, NSError *error) {
                          NSLog(@"-------%@", [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]);
                      }];
    */
   /* 处于安全性考虑,通常我们会使用POST方式进行文件上传,所以较多使用第二种方式.
    但是,NSURLSession并没有为我们提供比NSURLConnection更方便的文件上传方式.方法中body处的参数需要填写request的请求体(http协议规定格式的大长串).因为你有90%的可能性用了AFNetworking,即使是自己写的应该也是copy,所以代码就不贴了我们只说方法呵呵哒.
     */
    
}



- (IBAction)downloadRequest:(id)sender {
    
    [self downLoadOne];
    
//    [self doenLoadtwo];
    
}




#pragma mark --使用NSURLSession实现大文件(代理方式)
-(void)doenLoadtwo
{
    /*
     
     可以监控下载进度
     但不能实现断点下载,如果有断点下载的需求,可以阅读另外一篇博文 大文件离线断点下载
     
     遵守协议NSURLSessionDownloadDelegate,实现相应的代理方法
     
     */
    
    
    
    // 获得NSURLSession对象
    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[[NSOperationQueue alloc] init]];
    
    // 获得下载任务
    self.downloadTask = [session downloadTaskWithURL:[NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_01.mp4"]];
    
    // 启动任务
    [self.downloadTask resume];
    
}

#pragma mark - <NSURLSessionDownloadDelegate>

- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes
{
    
    /*
     2.恢复下载的时候调用该方法
     fileOffset:恢复之后,要从文件的什么地方开发下载
     expectedTotalBytes:该文件数据的总大小
     */
    NSLog(@"didResumeAtOffset");
}

/**
 * 每当写入数据到临时文件时,就会调用一次这个方法(会调用多次)
 * totalBytesExpectedToWrite:总大小
 * totalBytesWritten: 已经写入的大小
 * bytesWritten: 这次写入多少
 */
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
    //计算当前的下载进度
    NSLog(@"--------%f", 1.0 * totalBytesWritten / totalBytesExpectedToWrite);
}

// 下载完毕就会调用一次这个方法
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location
{
    // location还是一个临时路径,需要自己挪到需要的路径(caches下面)
    // 文件将来存放的真实路径
    NSString *file = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:downloadTask.response.suggestedFilename];
    NSLog(@"                  %@",file);
    // 剪切location的临时文件到真实路径
    NSFileManager *mgr = [NSFileManager defaultManager];
    [mgr moveItemAtURL:location toURL:[NSURL fileURLWithPath:file] error:nil];
}


//任务完成调用  (之前的代理方法已包括)

//- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
//{
//    NSLog(@"didCompleteWithError");
//}


#pragma mark --实现断点下载相关代码
-(void)downLoadTask
{
    //如果任务,取消了那么以后就不能恢复了
    //    [self.downloadTask cancel];
    
    //如果采取这种方式来取消任务,那么该方法会通过resumeData保存当前文件的下载信息
    //只要有了这份信息,以后就可以通过这些信息来恢复下载
    [self.downloadTask cancelByProducingResumeData:^(NSData * __nullable resumeData) {
        self.resumeData = resumeData;
    }];
    
    //继续下载
    //首先通过之前保存的resumeData信息,创建一个下载任务
    self.downloadTask = [[NSURLSession sharedSession] downloadTaskWithResumeData:self.resumeData];
    
    [self.downloadTask resume];
}


- (IBAction)stopDown:(id)sender {
    
    [self downloadTask];
}



#pragma mark --下载文件 --代理(普通的下载,图片之类)
-(void)downLoadOne
{
    //(1)创建NSURLSession对象,设置代理(默认配置)
    
    //1.创建NSURLSession,并设置代理
    /*
     第一个参数:session对象的全局配置设置,一般使用默认配置就可以
     第二个参数:谁成为session对象的代理
     第三个参数:代理方法在哪个队列中执行(在哪个线程中调用),如果是主队列那么在主线程中执行,如果是非主队列,那么在子线程中执行
     */
    NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    
    
    //(2)根据Session对象创建一个NSURLSessionDataTask任务(post和get选择)
    //创建task
    NSURL *url = [NSURL URLWithString:kImageURL];
    
    //注意:如果要发送POST请求,那么请使用dataTaskWithRequest,设置一些请求头信息
    NSURLSessionDataTask *dataTask = [session dataTaskWithURL:url];
    
    
    //(3)执行任务(其它方法,如暂停、取消等)
    //启动task
    [dataTask resume];
    //其它方法,如取消任务,暂停任务等
    //[dataTask cancel];
    //[dataTask suspend];

}

#pragma mark --NSURLSessionDataDelegate代理方法
//(4)遵守代理协议,实现代理方法(3个相关的代理方法)
/*
 1.当接收到服务器响应的时候调用
 session:发送请求的session对象
 dataTask:根据NSURLSession创建的task任务
 response:服务器响应信息(响应头)
 completionHandler:通过该block回调,告诉服务器端是否接收返回的数据
 */
-(void)URLSession:(nonnull NSURLSession *)session dataTask:(nonnull NSURLSessionDataTask *)dataTask didReceiveResponse:(nonnull NSURLResponse *)response completionHandler:(nonnull void (^)(NSURLSessionResponseDisposition))completionHandler
{
    
    
    
    //默认情况下,当接收到服务器响应之后,服务器认为客户端不需要接收数据,所以后面的代理方法不会调用
    //如果需要继续接收服务器返回的数据,那么需要调用block,并传入对应的策略
    
    /*
     NSURLSessionResponseCancel = 0, 取消任务
     NSURLSessionResponseAllow = 1,  接收任务
     NSURLSessionResponseBecomeDownload = 2, 转变成下载
     NSURLSessionResponseBecomeStream NS_ENUM_AVAILABLE(10_11, 9_0) = 3, 转变成流
     */
    
    
    
    // 允许处理服务器的响应,才会继续接收服务器返回的数据
    completionHandler(NSURLSessionResponseAllow);
    
}

/*
 2.当接收到服务器返回的数据时调用
 该方法可能会被调用多次
 */
-(void)URLSession:(nonnull NSURLSession *)session dataTask:(nonnull NSURLSessionDataTask *)dataTask didReceiveData:(nonnull NSData *)data
{
    [self.myData appendData:data];
    
    self.imageView.image = [UIImage imageWithData:self.myData];
}

/*
 3.当请求完成之后调用该方法
 不论是请求成功还是请求失败都调用该方法,如果请求失败,那么error对象有值,否则那么error对象为空
 */


-(void)URLSession:(nonnull NSURLSession *)session task:(nonnull NSURLSessionTask *)task didCompleteWithError:(nullable NSError *)error
{
    
}

#pragma mark -- 使用NSURLSessionDataTask实现大文件离线断点下载(完整)

-(void)initNSOutputStream
{
//6.1 涉及知识点

//(1)关于NSOutputStream的使用
//1. 创建一个输入流,数据追加到文件的屁股上
//把数据写入到指定的文件地址,如果当前文件不存在,则会自动创建
// NSOutputStream *stream = [[NSOutputStream alloc]initWithURL:[NSURL fileURLWithPath:[self fullPath]] append:YES];

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

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

//4.当不需要的时候应该关闭流
//[stream close];
//(2)关于网络请求请求头的设置(可以设置请求下载文件的某一部分)
//1. 设置请求对象
//1.1 创建请求路径
// NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_01.mp4"];

//1.2 创建可变请求对象
//NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];

//1.3 拿到当前文件的残留数据大小
// self.currentContentLength = [self FileSize];

//1.4 告诉服务器从哪个地方开始下载文件数据
// NSString *range = [NSString stringWithFormat:@"bytes=%zd-",self.currentContentLength];
// NSLog(@"%@",range);

//1.5 设置请求头
//[request setValue:range forHTTPHeaderField:@"Range"];
//(3)NSURLSession对象的释放
    
}
-(void)dealloc
{
    //在最后的时候应该把session释放,以免造成内存泄露
    //    NSURLSession设置过代理后,需要在最后(比如控制器销毁的时候)调用session的invalidateAndCancel或者resetWithCompletionHandler,才不会有内存泄露
    //    [self.session invalidateAndCancel];
//    [self.session resetWithCompletionHandler:^{
//        
//        NSLog(@"释放---");
//    }];
}


/*
 

 
 (3)关于NSURLSessionConfiguration相关
 01 作用:可以统一配置NSURLSession,如请求超时等
 02 创建的方式和使用
 //创建配置的三种方式
 + (NSURLSessionConfiguration *)defaultSessionConfiguration;
 + (NSURLSessionConfiguration *)ephemeralSessionConfiguration;
 + (NSURLSessionConfiguration *)backgroundSessionConfigurationWithIdentifier:(NSString *)identifier NS_AVAILABLE(10_10, 8_0);
 
 //统一配置NSURLSession
 -(NSURLSession *)session
 {
 if (_session == nil) {
 
 //创建NSURLSessionConfiguration
 NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
 
 //设置请求超时为10秒钟
 config.timeoutIntervalForRequest = 10;
 
 //在蜂窝网络情况下是否继续请求(上传或下载)
 config.allowsCellularAccess = NO;
 
 _session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]];
 }
 return _session;
 }
 
 
 
 
 
 */



@end

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值