NSURLConnection
 
1、准备网络资源地址:URL
注意:由于URL支持26个英文字母,数字和少数的几个特殊字符. 因此对于URL中包含非标准URL的字符,需要进行编码. iOS提供了函数 stringByAddPercentEscapesUsingEncoding对中文和一些特殊字符进行编码
2、发送数据请求
3、遵守协议:<NSURLConnectionDataDelegate>,处理下载任务时的事件
 
@interface ViewController ()<NSURLConnectionDataDelegate>
//用于存储网络下载的数据.把分包的数据整合起来.
@property (nonatomic, strong) NSMutableData *receivedData;

@end
//!!请注意URL地址必须包含http等协议的前缀. xcode并不会自动为我们添加.
//    NSURL OC的URL类型,地址资源定位
    NSURL *url = [NSURL URLWithString:@"http://www.tmooc.cn"];
// OC的请求类型,包含了请求相关的操作.例如缓存.cookie等等...
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
//    Immediately 立刻,马上
//    startImmediately 立刻开始
//    YES代表立刻开始请求,
//    NO 不需要立刻开始,需要手动触发.
    NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO];
//    手动开始请求
    [conn start];
}
 
//1、当收到服务器的请求响应,触发此代理
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
    NSLog(@"didReceiveResponse:%@", response);
    _receivedData = [[NSMutableData alloc] init];
}
//2、收到服务器传输的数据,如果数据量比较大的话,服务器会分批传,俗称数据包.
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
//    由于data有可能是分批的,所以我们需要一个全局的MutableData去拼接起来
    NSLog(@"didReceiveData:%ld个字节", data.length);
    [_receivedData appendData:data];
}
//3、连接成功被加载了
- (void)connectionDidFinishLoading:(NSURLConnection *)connection{
    NSLog(@"connectionDidFinishLoading");
//    写到沙盒的document文件夹下的baidu文件中
    NSString *path = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents/baidu"];
    NSLog(@"path is %@", path);
//    data类型转换为字符串,再存储
//    使用NSUTF8StringEncoding编码类型,对_receivedData这个二进制类型进行转码,转换为字符串
    NSString *baiduStr = [[NSString alloc] initWithData:_receivedData encoding:NSUTF8StringEncoding];
//    定义一个error指针,不需要初始化
//    error指针的初始化由下面的方法来完成. 如果有错误就会被赋值. 没错误,依然会是nil
    NSError *error = nil;
    [baiduStr writeToFile:path atomically:NO encoding:NSUTF8StringEncoding error:&error];
    if (error) {
//        error有值,则说明上面的写文件方法出错了
        NSLog(@"error:%@", error);
    }
}
 
//——————————————————--------------------—数据请求的方式----------------------------------------
//通常我们使用宏定义 或者 static的方式 在文件的顶端,声明文件中需要用到的常量
//好处:便于维护. 特别是一个常量 要很多个位置使用时
//习惯上,添加k为前缀
#define kBaiduURLString    @"http://www.baidu.com"
 
    [selfsendSyncRequest:kBaiduURLString];
 
异步请求:(在子线程执行)
- (void)sendAsyncRequest:(NSString *)urlString{
//转码: 对urlString进行标准化的编码,防止中文和特殊字符的出现
//    Percent 百分号,分数
    urlString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    NSURL *url = [NSURL URLWithString:urlString];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    NSLog(@"主线程是%@", [NSThread mainThread]);
//异步请求方法:
    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
//下载结束后的处理:
        NSLog(@"在线程%@中处理",[NSThread currentThread]);
        NSLog(@"接收到%ld字节的数据", data.length);
    }];
}
 
同步请求:(不用,在主线程执行)
    urlString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    NSURL *url = [NSURL URLWithString:urlString];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
//    用于存储服务器返回的响应,参考delegate方式中的didReceiveResponse
    NSURLResponse *response = nil;
    NSError *error = nil;
//    发送同步请求
    NSTimeInterval beginTime =[NSDate timeIntervalSinceReferenceDate];
    NSData *receivedData =[NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
    NSLog(@"接收到%ld个字节的数据", receivedData.length);
    NSTimeInterval endTime = [NSDate timeIntervalSinceReferenceDate];
    NSLog(@"请求耗时%f秒", endTime - beginTime);
//——————————————————------------------------—End--------------------------------------------
 
//———————————————————-------------------断点下载----------------------------------------------
服务器: 被动的角色
客户端: 主动的角色
客户端必须告诉服务器当前应该从哪个地方开始继续下载

如何告诉, 通过http协议的数据包?
客户端 —http> 服务器
key(BigFile.zip: 600M):

1) 客户端Request请求头中Range: bytes=100-200 ;—> 服务器从100bytes开时发送给客户端, 直到200bytes
2) 客户端Request请求头中Range: bytes=100- ;—> 服务器从100bytes开时发送给客户端, 直到发送完毕为止
步骤:
1. 使用NSFileManager在didReceiveResponse方法中创建一个空的文件(在沙盒中的caches路径下),获取文件的总大小
2. 在didReceiveData方法中: 首先将writeHandler移到文件的最后, 之后再将数据写入文件中.
3. 在DidFinishLoading方法中, 对属性重新初始化,在关闭文件写句柄
 
//Caches路径
@property(nonatomic,strong)NSString *cachePath;
@property(nonatomic,strong)NSFileHandle *writeHandle;
@property(nonatomic,assign)long long currentLength;//已下载的文件的大小(以字节为单位)
@property(nonatomic,assign)long long totalLength;//文件的总大小
//断点传输
@property(nonatomic,strong)NSMutableURLRequest *request;//要使用可变的请求对象
@property(nonatomic,strong)NSURLConnection *conn;

@end
@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.cachePath=[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)firstObject];

 
}
- (IBAction)downloadBigFile:(UIButton *)sender {
    NSURL *url=[NSURL URLWithString:@"http://localhost:80/Evernote.zip"];
 
    self.totalLength=0;
    self.currentLength=0;
    self.request=[NSMutableURLRequest requestWithURL:url];
    //设置range:bytes=0-
    NSString *range= [NSString stringWithFormat:@"bytes=%lld-",self.currentLength];
    [self.request setValue:range forHTTPHeaderField:@"Range"];
    self.conn = [NSURLConnection connectionWithRequest:self.request delegate:self];
}
- (IBAction)cancelDownLoad:(UIButton *)sender {
    //取消下载
    [self.conn cancel];
    self.conn=nil;
}
- (IBAction)resumeDownLoad:(UIButton *)sender {
    //恢复下载
    //Range:bytes=
    NSString *range=[NSString stringWithFormat:@"bytes=%lld-",self.currentLength];
    [self.request setValue:range forHTTPHeaderField:@"Range"];
    self.conn = [NSURLConnection connectionWithRequest:self.request delegate:self];
}
//客户端请求成功,接收到响应response
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
//获取返回的代号,判断出服务器响应的结果
    NSInteger status=[(NSHTTPURLResponse *)response statusCode];
    NSLog(@"status:%ld",(long)status);
    if (status == 206) {
        //在沙盒Caches/文件夹下,创建出用来存储数据的文件
        NSFileManager *manage=[NSFileManager defaultManager];
        NSString *fliePath=[self.cachePath stringByAppendingPathComponent:@"text.zip"];
        NSLog(@"写入的文件路径:%@",fliePath);
        [manage createFileAtPath:fliePath contents:nil attributes:nil];
        //获取文件的总大小(为了显示进度)
        self.writeHandle=[NSFileHandle fileHandleForWritingAtPath:fliePath];
        if (self.currentLength ==0) {//服务器返回文件的剩余大小,因此要获取一次返回的大小
            self.totalLength=response.expectedContentLength;
        } 
        NSLog(@"文件的总大小:%lld",self.totalLength); 
    }
}
//接收到数据
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
    //当前接收数据包的大小
    static int i=0;
    i++;
    NSLog(@"当前接收数据大小_%d:%ld",i,(unsigned long)data.length);
    //移动到文件尾部
    [self.writeHandle seekToEndOfFile];
   //写入文件
    [self.writeHandle writeData:data];
    self.currentLength +=data.length;
    NSLog(@"总接收数据:%lld",self.currentLength);
    self.progressView.progress = (double)self.currentLength / self.totalLength;
    NSLog(@"当前进度:%f",self.progressView.progress);
}
//下载完成后,关闭句柄
-(void)connectionDidFinishLoading:(NSURLConnection *)connection{
    [self.writeHandle closeFile];
}
//错误处理
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
    NSLog(@"error : %@",[error userInfo])
}
 
//*********************************************
苹果公司在iOS7,给SDK中添加了新的网络处理类:NSURLSession
它与URLConnection是并列关系.
URLSession包含了URLConnection的所有功能, 额外还添加了以下4点特性:
1.通过URL将数据下载到内存
2.通过URL将数据下载到文件系统
3.将数据上传到指定的URL
4.在后台完成上述的操作
适用场景:     ios7+; 封装很多实现细节;
使用NSURLSession之前
选择工作模式:
session(会话)三个类型:
session1  <- defaultSessionConfiguration:(默认模式),类似于原来的NSURLConnection,使用的是基于磁盘缓存的持久化策略,使用用户keychain中保存的证书进行认证授权
session2  <- ephemeralSessionConfiguration:(瞬时模式),不会在磁盘中保存任何数据,所有与会话有关的caches、证书、cookies等都保存在RAM中,因此当程序会话无效时,这些缓存数据就会被自动清理。
session3  <- backgroundSessionConfiguration:(后台模式),在后天完成上传和下载,在创建congfiguration对象的时候需要提供一个NSString类型的ID用来标示完成工作的后台会话。
task三个类型:
1、NSURLSessionDataTask:
     处理小数据相关的任务(不包括下载和上传)
     例子: 返回json数据; 返回html文件(放在UIWebView);
               返回xml数据
2、NSURLSessionDownloadTask:
//采用的是子线程下载
     主要用于下载任务; delegate方法接收或者处理服务器返回的数据
3、NSURLSessionUploadTask:
     主要用于上传任务;
后台运行:
主要configuration的配置: backgroundSessionConfiguration
获得NSURLSession对象:
第一种方式是使用静态的sharedSession方法,该类使用共享的会话,该会话使用全局的Cache,Cookie和证书。
第二种方式是通过sessionWithConfiguration:方法创建对象,也就是创建对应配置的会话,与NSURLSessionConfiguration合作使用。
第三种方式是通过sessionWithConfiguration:delegate:delegateQueue方法创建对象,二三两种方式可以创建一个新会话并定制其会话类型。该方式中指定了session的委托和委托所处的队列。当不再需要连接时,可以调用Session的invalidateAndCancel直接关闭,或者调用finishTasksAndInvalidate等待当前Task结束后关闭。这时Delegate会收到URLSession:didBecomeInvalidWithError:这个事件。Delegate收到这个事件之后会被解引用。
 
//---------------------------------使用步骤--------------------------------------------------------
1、准备网络资源地址URL、发送请求NSURLRequest
2、创建NSURLSession对象
3、执行下载任务NSURLSessionDownloadTask
4、下载完成后,对文件的处理
NSURLSessionDownloadTask  *downloadTask=[session downloadTaskWithRequest:request
                    completionHandler:^(NSURL *location,//location是位于沙盒中的tmp目录下,要转移(会被定时清理的) 
                    NSURLResponse *response,//服务器的响应
                    NSError *error){
          });
//------------------------------------------------------------------------------------------------
//————————————————-----------—————简单的使用方式-------------------------------------------
 
- (IBAction)downLoad:(UIButton *)sender {
    //1创建NSURLSession对象
    NSURLSession *session=[NSURLSession sharedSession];//使用默认的session(回话)方式
    NSURLRequest *request=[NSURLRequest requestWithURL:[NSURL URLWithString:@"https://ss1.bdstatic.com/70cFvXSh_Q1YnxGkpoWK1HF6hhy/it/u=298400068,822827541&fm=116&gp=0.jpg"]];
    NSURLSessionDownloadTask  *downloadTask=[session downloadTaskWithRequest:request completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
        NSLog(@"下载完成:%@",[NSThread currentThread]);//子线程
       
        NSInteger status=[(NSHTTPURLResponse *)response statusCode];//服务器返回的编号
        NSLog(@"status:%ld",(long)status);
        if (status ==200) {
            NSLog(@"location:%@",location);
//location是位于沙盒中的tmp目录下,要转移(会被定时清理的)
//要将文件转移到Caches中
            //1、获取路径
            NSLog(@"response : %@",response);
            NSString *path=[[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)firstObject]stringByAppendingPathComponent:@"mm.jpg"];
            NSLog(@"path :%@",path);
            //2、移动文件
            [[NSFileManager defaultManager]moveItemAtPath:location.path toPath:path error:nil];
            //显示图片
            UIImage *image=[UIImage imageNamed:path];
//4.回到主线程将图片显示在界面上,为什么要回到主线程?答:因为视图层都在主线程中
            dispatch_async(dispatch_get_main_queue(), ^{
                self.imageView.image=image;
            });
        }
    }];
    //执行下载任务
    [downloadTask resume];
}
//------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------
//------------------------------------------------------------------------------------------------

NSURLConnection、NSURLSession的更多相关文章

  1. NSURLConnection、NSURLSession 补充

    一.大文件下载1.方案:利用NSURLConnection和它的代理方法1> 发送一个请求 // 1.URL NSURL *url = [NSURL URLWithString:@"h ...

  2. iOS开发之网络编程--1、NSURLSession的基本使用

    前言:学习NSURLSession的使用之前,先学习一篇关于NSURLSession的好文章<From NSURLConnection to NSURLSession>或者是国内的译文&l ...

  3. iOS网络学习之“远离NSURLConnection 走进NSURLSession”

    目前,在iOS的开发中,NURLConnection已经成为了过去式,现在的NSURLConnection已经deprected(iOS7之后),取而代之的是NSURLSession.而且AFNetw ...

  4. 从 NSURLConnection 到 NSURLSession

    iOS 7 和 Mac OS X 10.9 Mavericks 中一个显著的变化就是对 Foundation URL 加载系统的彻底重构. 现在已经有人在深入苹果的网络层基础架构的地方做研究了,所以我 ...

  5. 简单使用NSURLConnection、NSURLRequest和NSURL

    以下是代码,凝视也写得比較清楚: 头文件须要实现协议NSURLConnectionDelegate和NSURLConnectionDataDelegate // // HttpDemo.h // My ...

  6. 使用NSURLProtocol和NSURLSession拦截UIWebView的HTTP请求(包括ajax请求)

    问题:服务器端有一个网站需要AD认证,整站都开了Basic认证,包括图片,CSS等资源,我在HTTP请求头里面添加认证所需的用户名和密码,传递到服务器端可以认证通过.我在UIWebView的shoul ...

  7. 【原】HTTP in iOS你看我就够

    声明:本文是本人 编程小翁 原创,转载请注明. 本文同步发布在简书中,强烈建议移步简书查看,编程小翁 HTTP属于老话题了,在项目中我们经常需要往服务端发POST或者GET请求,但是对于HTTP的了解 ...

  8. iOS网络相关知识总结

    iOS网络相关知识总结 1.关于请求NSURLRequest? 我们经常讲的GET/POST/PUT等请求是指我们要向服务器发出的NSMutableURLRequest的类型; 我们可以设置Reque ...

  9. HTTP in iOS你看我就够

    HTTP属于老话题了,在项目中我们经常需要往服务端发POST或者GET请求,但是对于HTTP的了解不应只局限于此.千里之行,始于足下.越想走的远,基本原理就应该了解的透彻全面一些,仅仅停留在使用ASI ...

随机推荐

  1. Spark中的编程模型

    1. Spark中的基本概念 Application:基于Spark的用户程序,包含了一个driver program和集群中多个executor. Driver Program:运行Applicat ...

  2. 怎么利用SQL语句查询数据库中具体某个字段的重复行

    select * from [tablename] group by SeriNohaving count(SeriNo)<>1

  3. tensorflow-cnn

    需要安装 python,numpy,tensorflow,运行代码即可. tensorflow很好装,用pip安装即可. 可以参照http://wiki.jikexueyuan.com/project ...

  4. Android 用MediaCodec实现视频硬解码(转)

    本文向你讲述如何用android标准的API (MediaCodec)实现视频的硬件编解码.例程将从摄像头采集视频开始,然后进行H264编码,再解码,然后显示.我将尽量讲得简短而清晰,不展示 那些不相 ...

  5. Web Service学习之八:Soap消息详解

    一.区别概念 WSDL是网络服务描述语言,是XML文档:它包含一系列描述某个web service的定义或者说是规则.尤其是定义了传输Sope消息的结构 Soap:简单对象访问协议,是交换数据的一种协 ...

  6. DATASNAP多表提交之事务控制之通用方法

    ERP系统的单据,总是些主从表结构,有一个主表,N个子表,子表又有子表,形成N层,单据数据提交时,主从表数据都要提交,为了保证数据的完整性,必须提供事务控制,要么都提交成功,有一个提交失败所有的提交都 ...

  7. 创建类模式(三):创建者(Builder)

    定义 将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示.这使得构件算法和组装方式可以独立应对变化:复用同样的构建算法可以创建不同的表示,不同的构建过程可以复用相同的部件组装方式 ...

  8. getopt使用例子

    getopt是linux下获取程序启动参数的函数        #include <unistd.h> int getopt(int argc, char * const argv[], ...

  9. 网络复习之TCP

    可靠传输的工作原理 1 停止等待协议 每发送完一个分组,就停止发送,等待对方确认.出现差错,超时重传.     1.1 暂时保留已发送的分组的副本     1.2 分组和确认分组必须进行编号     ...

  10. AngularJS应用的解析

    模板(Templates) 模板是您用HTML和CSS编写的文件,展现应用的视图. 您可给HTML添加新的元素.属性标记,作为AngularJS编译器的指令. AngularJS编译器是完全可扩展的, ...