NSURLSession的常用知识

/*--------------------- 01  NSURLSession -------------------*/

重点:1.NSURLSession的使用 2.熟练掌握 NSURLSession

{

<1> NSURLSession 简介:

{

NSURLSession 是 iOS 7.0 之后推出的网络解决方案!用于替代 NSURLConnection,  针对下载/上传等复杂的网络操作提供了专门的解决方案!

NSURLSession 使用更加简单/方便!

}

<2> NSURLSession 中新增的内容:

{

1> 全局的 NSURLSession 对象: 所有的网络会话都由一个 NSURLSession 对象发起, 实例化一个 NSURLSession 对象有两种方法:

{

*1 对于简单的,不需要监听网络请求过程的网络会话来说,使用系统提供的,全局的 NSURLSession 单利对象:

NSURLSession *session = [NSURLSession sharedSession];

*2 如果需要监听网络进度,需要自定义一个 NSURLSession 对象,并且设置代理!这时还需要一个 NSURLSessionConfiguration,可以设置全局的网络访问属性.

NSURLSessionConfiguration *cfg = [NSURLSessionConfiguration defaultSessionConfiguration];

NSURLSession *session = [NSURLSession sessionWithConfiguration:cfg delegate:self delegateQueue:[NSOperationQueue mainQueue]];

}

2> 网络任务(Task);在 NSURLSession 中,有三种网络任务类型.

{

*1 用于非文件下载的普通的 GET/POST请求 NSURLSessionDataTask.实例化对象有以下2种方法:

{

// 1> 通过一个 request 实例化普通网络任务,增加完成之后的 block 回调,使用比较多.

NSURLSessionDataTask *task = [self.session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {

}];

// 2> 通过一个 url 实例化普通网络任务,增加完成之后的 block 回调,使用比较多.

NSURLSessionDataTask *task = [self.session dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {

}];

}

*2 用于文件下载的网络任务 NSURLSessionDownloadTask (无论文件大小,下载都使用 NSURLSessionDownloadTask) ,实例化对象有以下三种方法:

{

// 1> 通过一个 request 实例化下载网络任务,增加任务完成之后的 block 回调,一般用在小文件下载.

NSURLSessionDownloadTask *task = [self.session downloadTaskWithRequest:request completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {

}];

// 2> 通过一个 url 实例化下载网络任务,增加任务完成之后的 block 回调,一般用在小文件下载.

NSURLSessionDownloadTask *task = [self.session downloadTaskWithURL:url completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {

}];

// 3> 通过之前下载的数据 ResumeData ,实例化一个下载任务,用于断点续传.

NSURLSessionDownloadTask *task = [session downloadTaskWithResumeData:ResumeData completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {

}];

}

*3 用于文件上传的网络任务 NSURLSessionUploadTask.

{

// 目前,只有通过这种方式实例化的下载任务,才能实现文件上传.依然需要拼接数据.

NSURLSessionUploadTask *task = [session uploadTaskWithRequest:request fromData:fromData completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {

//

}]

}

}

}

<3> NSURLSession 的使用分为三步:

{

1> 实例化一个 NSURLSession 对象 session ;

NSURLSession *session = [NSURLSession sharedSession];

2> 通过 NSURLSession 对象,实例化对应的网络任务 task;

NSURLSessionDataTask *task = [session dataTaskWithRequest:request];

3> 开启网络任务

[task resume];

}

}

/*-----------------  02 NSURLSession 下载的断点续传 ------------------*/

重点:1.学会使用 NSULSession 实现下载任务. 2.实时监听下载进度,学会使用断点续传.

{   

 利用 NSURLSession 实现文件下载,首先需要创建一个 NSURLSessionDownloadTask; 由于需要实时监听下载进度,所以,需要实现方法,这样,就需要自定义一个会话 session.并且制定代理.

// NSURLSession 下载的断点续传实现步骤:

1. 懒加载全局网络会话

{

-(NSURLSession *)session

{

if (!_session) {

NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];

_session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil];

}

return _session;

}

}

2. 利用全局网络会话,创建下载 task, 开始下载任务

{

self.task = [self.session downloadTaskWithURL:url];

[self.task resume];

}

3. 在代理方法中,实时监听下载进度

{

// 监听下载进度的方法

// bytesWritten :本次下载的字节数

// totalBytesWritten :已经下载的字节数

// totalBytesExpectedToWrite :下载文件的总字节数

-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite

{

NSLog(@"代理回调~");

float progress = (float)totalBytesWritten/totalBytesExpectedToWrite;

dispatch_async(dispatch_get_main_queue(), ^{

self.progress.progress = progress;

});

}

// 完成下载的时候调用

-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location

{

NSLog(@"下载完成%@",location);

}

// 断点续传的代理方法,暂时什么都不写

-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes

{

NSLog(@"%s",__FUNCTION__);

}

}

4. 当点击暂停之后,应该取消下载任务,记录当前下载的文件数据,并且将 task 任务设为 nil

{

[self.task cancelByProducingResumeData:^(NSData *resumeData) {

self.reusemData = resumeData;

self.task = nil;

}];

}

5. 当点击继续之后,应该从上次下载的进度继续下载,这时,重新创建下载 task, 并且是根据上次记录的文件下载数据来实例化下载任务

{

if (!self.reusemData) {

return;

}

self.task = [self.session downloadTaskWithResumeData:self.reusemData];

self.reusemData = nil;

[self.task resume];

}

}

/*--------------------- 03 NSURLSession 实现上传文件 -----------------*/

重点:1.学会使用 NSURLSession 实现文件上传.

{

NSURLSession 上传文件和 NSURLConnection 一样需要按格式拼接文件数据.重要的是要学会封装方法,具体使用如下:

{

// NSURLSession 做文件上传

- (void)uploadMfileSession

{

// 1.实例化全局网络会话

NSURLSession *session = [NSURLSession sharedSession];

// 2.创建网络请求

{

NSURL *url = [NSURL URLWithString:@"http://localhost/upload/upload-m.php"];

NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];

// 设置请求方法

request.HTTPMethod = @"POST";

// 告诉服务器,需要做文件上传

NSString *contentType = [NSString stringWithFormat:@"multipart/form-data; boundary=%@",kBOUNDARY];

[request setValue:contentType forHTTPHeaderField:@"Content-Type"];

}

// 3. 将需要上传至服务器的文件包装在字典中.

{

// 需要上传的文件路径

NSString *file1 = @"/Users/likaining/Desktop/meinv.jpg";

NSString *file2 = @"/Users/likaining/Downloads/XMLdemo.xml";

// 文件在服务器中保存的名称

NSString *fileName1 = @"meinv";

NSString *fileName2 = @"demo";

// 将上传数据包装在字典中

NSMutableDictionary *fileDict = [NSMutableDictionary dictionary];

[fileDict setObject:file1 forKey:fileName1];

[fileDict setObject:file2 forKey:fileName2];

}

// 4. 将需要上传的非文件数据也包装在字典中

{

NSMutableDictionary *parameter = [NSMutableDictionary dictionary];

[parameter setObject:@"likaining" forKey:@"username"];

}

// 5. 将需要上传的数据,按照上传的数据格式化数据.并且转为二进制数据.

NSData *dataM = [self formDataWithfileName:@"userfile[]" fileDict:fileDict parameter:parameter];

// 6. 利用网络会话,建立上传任务

NSURLSessionUploadTask *task = [session uploadTaskWithRequest:request fromData:dataM completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {

//

NSLog(@"%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);

NSLog(@"response: %@",response);

}];

// 7 .开始上传.

[task resume];

}

// 格式化上传数据的方法封装.

- (NSData *) formDataWithfileName:(NSString *)fileName fileDict:(NSDictionary *)fileDict parameter:(NSDictionary *)parameter

{

NSMutableData *data = [NSMutableData data];

// key : 服务器保存的文件名

// obj : 上传的文件地址

[fileDict enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {

//

NSMutableString *headerStrM = [NSMutableString stringWithFormat:@"\r\n--%@\r\n",kBOUNDARY];

[headerStrM appendFormat:@"Content-Disposition: form-data; name=%@; filename=%@\r\n",fileName,key];

NSString *contentType = [self getContentTypeFromFile:obj];

[headerStrM appendFormat:@"Content-Type: %@\r\n\r\n",contentType];

NSData *headerData = [headerStrM dataUsingEncoding:NSUTF8StringEncoding];

NSData *fileData = [NSData dataWithContentsOfFile:obj];

[data appendData:headerData];

[data appendData:fileData];

}];

// key :username 服务器接收的 key

// obj :上传文件的人

[parameter enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {

//

NSMutableString *headerM = [NSMutableString stringWithFormat:@"\r\n--%@\r\n",kBOUNDARY];

[headerM appendFormat:@"Content-Disposition: form-data; name=%@\r\n\r\n",key];

NSString *username = obj;

NSData *headerData = [headerM dataUsingEncoding:NSUTF8StringEncoding];

NSData *userData = [username dataUsingEncoding:NSUTF8StringEncoding];

[data appendData:headerData];

[data appendData:userData];

}];

NSMutableString *footerStrM = [NSMutableString stringWithFormat:@"\r\n--%@--\r\n",kBOUNDARY];

NSData *footerData = [footerStrM dataUsingEncoding:NSUTF8StringEncoding];

[data appendData:footerData];

return data;

}

}

}

/*------------------- 04 文件的复制和剪切 ----------------------*/

重点:掌握文件操作中的复制和剪切.

{

文件下载到本地之后,有时候需要对文件进行移动操作,这样就需要掌握掌握文件的复制和剪切操作.

1.文件的拷贝

// 新建一个文件路径

NSString *path = @"/Users/likaining/Desktop/abc/";

// 从一个文件路径拷贝文件到另一个文件路径

// AtPath : 拷贝前的文件路径

// ToPath : 拷贝后的文件路径

[[NSFileManager defaultManager] copyItemAtPath:location.path toPath:path error:0];

2.文件的剪切

// response.suggestedFilename:建议使用的文件名,一般跟服务器端的文件名一致

NSString *file = [caches stringByAppendingPathComponent:downloadTask.response.suggestedFilename];

// 将临时文件剪切到Caches文件夹

// AtPath : 剪切前的文件路径

// ToPath : 剪切后的文件路径

[[NSFileManager defaultManager] moveItemAtPath:location.path toPath:file error:nil];

}

/*------------------------- 05 文件的解压缩---------------------*/

重点:掌握文件的解压缩操作,会使用解压缩框架.

{

为了方便网络传输,文件经常被压缩之后再进行网络传输,这个时候,需要学会解压缩文件.

1.文件的解压缩需要导入第三方框架: SSZipArchive ,需要注意的是,这个框架依赖一个动态度 libz.dylib.

2. 压缩文件:

// 1.获得需要压缩的文件夹

NSString *images = [caches stringByAppendingPathComponent:@"images"];

// 1.创建一个zip文件(压缩)

NSString *zipFile = [caches stringByAppendingPathComponent:@"images.zip"];

BOOL result = [SSZipArchive createZipFileAtPath:zipFile withContentsOfDirectory:images];

3. 解压缩文件:

// location.path:需要解压缩的文件

// 文件解压缩之后存放的路径(注意,只需要给出一个文件路径就可以,因为很可能解压缩之后,生成很多个文件).

[SSZipArchive unzipFileAtPath:location.path toDestination:path];

}

                                  NSURLSessionConfiguration

NSURLSessionConfiguration对象用于初始化NSURLSession对象。

展开请求级别中与NSMutableURLRequest相关的可供选择的方案,我们可以看到NSURLSessionConfiguration对于会话如何产生请求,提供了相当多的控制和灵活性。从网络访问性能,到cookie,安全性,缓存策略,自定义协议,启动事件设置,以及用于移动设备优化的几个新属性,你会发现你一直在寻找的,正是NSURLSessionConfiguration。

会话在初始化时复制它们的配置,NSURLSession有一个只读的配置属性,使得该配置对象上的变化对这个会话的政策无效。配置在初始化时被读取一次,之后都是不会变化的。

-构造方法

NSURLSessionConfiguration有三个类构造函数,这很好地说明了NSURLSession是为不同的用例而设计的。

+ "defaultSessionConfiguration"返回标准配置,这实际上与NSURLConnection的网络协议栈是一样的,具有相同的共享NSHTTPCookieStorage,共享NSURLCache和共享NSURLCredentialStorage。

+ "ephemeralSessionConfiguration"返回一个预设配置,没有持久性存储的缓存,Cookie或证书。这对于实现像"秘密浏览"功能的功能来说,是很理想的。

+ "backgroundSessionConfiguration":独特之处在于,它会创建一个后台会话。后台会话不同于常规的,普通的会话,它甚至可以在应用程序挂起,退出,崩溃的情况下运行上传和下载任务。初始化时指定的标识符,被用于向任何可能在进程外恢复后台传输的守护进程提供上下文。

想要查看更多关于后台会话的信息,可以查看WWDC Session 204: “What’s New with Multitasking”

-NSURLSessionConfiguration的属性

NSURLSessionConfiguration拥有20个属性。熟练掌握这些属性的用处,将使应用程序充分利用其网络环境。

最重要的属性:

# 替代 request 中的 forHTTPHeaderField 告诉服务器有关客户端的附加信息

"HTTPAdditionalHeaders"指定了一组默认的可以设置出站请求的数据头。这对于跨会话共享信息,如内容类型,语言,用户代理,身份认证,是很有用的。

# WebDav的身份验证

NSString *userPasswordString = [NSString stringWithFormat:@"%@:%@", user, password];

NSData * userPasswordData = [userPasswordString dataUsingEncoding:NSUTF8StringEncoding];

NSString *base64EncodedCredential = [userPasswordData base64EncodedStringWithOptions:0];

NSString *authString = [NSString stringWithFormat:@"Basic: %@", base64EncodedCredential];

# 设置客户端类型

NSString *userAgentString = @"iPhone AppleWebKit";

configuration.HTTPAdditionalHeaders = @{@"Accept": @"application/json",

@"Accept-Language": @"en",

@"Authorization": authString,

@"User-Agent": userAgentString};

"networkServiceType(网络服务类型)"对标准的网络流量,网络电话,语音,视频,以及由一个后台进程使用的流量进行了区分。大多数应用程序都不需要设置这个

"allowsCellularAccess(允许蜂窝访问)"和"discretionary(自行决定)"被用于节省通过蜂窝连接的带宽。建议在使用后台传输的时候,使用discretionary属性,而不是allowsCellularAccess属性,因为它会把WiFi和电源可用性考虑在内

"timeoutIntervalForRequest"和"timeoutIntervalForResource"指定了请求以及该资源的超时时间间隔。许多开发人员试图使用timeoutInterval去限制发送请求的总时间,但这误会了timeoutInterval的意思:报文之间的时间。timeoutIntervalForResource实际上提供了整体超时的特性,这应该只用于后台传输,而不是用户实际上可能想要等待的任何东西

"HTTPMaximumConnectionsPerHost"是 Foundation 框架中URL加载系统的一个新的配置选项。它曾经被用于NSURLConnection管理私人连接池。现在有了NSURLSession,开发者可以在需要时限制连接到特定主机的数量

"HTTPShouldUsePipelining"也出现在NSMutableURLRequest,它可以被用于开启HTTP管道,这可以显着降低请求的加载时间,但是由于没有被服务器广泛支持,默认是禁用的

"sessionSendsLaunchEvents" 是另一个新的属性,该属性指定该会话是否应该从后台启动

"connectionProxyDictionary"指定了会话连接中的代理服务器。同样地,大多数面向消费者的应用程序都不需要代理,所以基本上不需要配置这个属性

关于连接代理的更多信息可以在 CFProxySupport Reference 找到。

"Cookie Policies"

-"HTTPCookieStorage" 是被会话使用的cookie存储。默认情况下,NSHTTPCookieShorage的 + sharedHTTPCookieStorage会被使用,这与NSURLConnection是相同的

-"HTTPCookieAcceptPolicy" 决定了该会话应该接受从服务器发出的cookie的条件

-"HTTPShouldSetCookies" 指定了请求是否应该使用会话HTTPCookieStorage的cookie

"Security Policies"

URLCredentialStorage 是会话使用的证书存储。默认情况下,NSURLCredentialStorage 的+ sharedCredentialStorage 会被使用使用,这与NSURLConnection是相同的

"TLSMaximumSupportedProtocol" 和 "TLSMinimumSupportedProtocol" 确定是否支持SSLProtocol版本的会话

"Caching Policies"

URLCache 是会话使用的缓存。默认情况下,NSURLCache 的 + sharedURLCache 会被使用,这与NSURLConnection是相同的

requestCachePolicy 指定了一个请求的缓存响应应该在什么时候返回。这相当于NSURLRequest 的-cachePolicy方法

"Custom Protocols"

protocolClasses是注册NSURLProtocol类的特定会话数组

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容