天天看点

iOS网络(一): Http协议通信及NSURLConnection的GET和POST方法,小文件下载

现在的移动开发必然涉及到服务器,那就不能不说网络。在网络编程中,有几个基本的概念:

  • 客户端(Client): 移动应用 (iOS, Android等应用)
  • 服务器(Server): 为客户端提供服务、提供数据、提供资源的机器
  • 请求(Request): 客户端向服务器索取数据的一种行为
  • 响应(Response): 服务器对客户端的请求作出响应,一般指返回数据给客户端

图解:

  • iOS网络(一): Http协议通信及NSURLConnection的GET和POST方法,小文件下载

 客户端是如何找到服务器呢,主要是通过URL找到想要连接的服务器,而什么是URL?

  • URL的全称是 Uniform Resource Locator (统一起源定位符)
  • 通过1个URL,能找到互联网上唯一的一个资源
  • URL就是资源的地址,位置,互联网上的每一个资源都有唯一的URL
  • URL的基本格式 = 协议://主机地址/路径(http://www.baidu.com/img/logo.png)

       协议: 不同的协议,代表着不同的资源查找方式,资源传输方式

       主机地址: 存放资源的主机(服务器)的IP地址(域名)

       路径: 资源在主机(服务器)中的具体位置

iOS网络(一): Http协议通信及NSURLConnection的GET和POST方法,小文件下载

HTTP协议的特点:

  • 简单快速

因为http协议简单,所以Http服务器的程序规模小,因而通信速度很快

  • 灵活

Http允许各种各样的数据

Http协议规定: 一个完整的由客户端和服务器端的Http请求包括以下内容:

iOS网络(一): Http协议通信及NSURLConnection的GET和POST方法,小文件下载
iOS网络(一): Http协议通信及NSURLConnection的GET和POST方法,小文件下载
iOS网络(一): Http协议通信及NSURLConnection的GET和POST方法,小文件下载

iOS中发送Http的请求方案:

  • 苹果原生:NSURLConnection(比较古老,不推荐使用), NSURLSession(推荐使用)
  • 第三方框架: AFNetworking
iOS网络(一): Http协议通信及NSURLConnection的GET和POST方法,小文件下载
iOS网络(一): Http协议通信及NSURLConnection的GET和POST方法,小文件下载
iOS网络(一): Http协议通信及NSURLConnection的GET和POST方法,小文件下载

NSURLConnection的GET

  1. 常用类
  • NSURL:请求地址
  •  NSURLRequest:一个NSURLRequest对象就代表一个请求,它包含的信息有(一个NSURL对象, 请求方法、请求头、请求体,请求超时......)
  • NSMutableURLRequest:NSURLRequest的子类
  • NSURLConnection (负责发送请求,建立客户端和服务器的连接发送数据给服务器,并收集来自服务器的响应数据)

    2.   NSURLConnection的使用步骤

  • 创建一个NSURL对象,设置请求路径
  • 传入NSURL创建一个NSURLRequest对象,设置请求头和请求体
  • 使用NSURLConnection发送请求
iOS网络(一): Http协议通信及NSURLConnection的GET和POST方法,小文件下载

3. 发送同步请求: 主要使用+ (NSData *)sendSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse **)response error:(NSError **)error;方法

/*
     GET:http://120.25.226.186:32812/login?username=123&pwd=456&type=JSON
     协议+主机地址+接口名称+?+参数1&参数2&参数3
     post:http://120.25.226.186:32812/login
     协议+主机地址+接口名称
     */
    //GET,没有请求体
    //1.确定请求路径
    NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login?username=520it&pwd=520it&type=JSON"];
    
    //2.创建请求对象
    //请求头不需要设置(默认的请求头)
    //请求方法--->默认为GET
    NSURLRequest *request = [[NSURLRequest alloc]initWithURL:url];
    
    //3.发送请求
    //真实类型:NSHTTPURLResponse
    NSHTTPURLResponse *response = nil;
    /*
     第一个参数:请求对象
     第二个参数:响应头信息
     第三个参数:错误信息
     返回值:响应体
     */
    //该方法是阻塞的,即如果该方法没有执行完则后面的代码将得不到执行
    NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil];
    
    //4.解析 data--->字符串
    //NSUTF8StringEncoding
    NSLog(@"%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
    
    NSLog(@"%zd",response.statusCode);
           

4. 发送异步请求: 主要使用两类方法

  • Block方法

+ (void)sendAsynchronousRequest:(NSURLRequest*) request  queue:(NSOperationQueue*) queue                                                  completionHandler:(void (^)(NSURLResponse* response, NSData* data, NSError* connectionError)) handler;

//1.确定请求路径
    NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login?username=520it&pwd=520it&type=JSON"];
    
    //2.创建请求对象
    //请求头不需要设置(默认的请求头)
    NSURLRequest *request = [[NSURLRequest alloc]initWithURL:url];
    
    //3.发送异步请求
    /*
     第一个参数:请求对象
     第二个参数:队列 决定代码块completionHandler的调用线程
     第三个参数:completionHandler 当请求完成(成功|失败)的时候回调
        response:响应头
        data:响应体
        connectionError:错误信息
     */
    [NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc]init] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
        
       
        //4.解析数据
        NSLog(@"%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
        
        NSHTTPURLResponse *res = (NSHTTPURLResponse *)response;
        NSLog(@"%zd",res.statusCode);
        NSLog(@"%@",[NSThread currentThread]);
    }];
           
  • 代理方法
- (id)initWithRequest:(NSURLRequest *)request delegate:(id)delegate;
           
+ (NSURLConnection*)connectionWithRequest:(NSURLRequest *)request delegate:(id)delegate;
           
- (id)initWithRequest:(NSURLRequest *)request delegate:(id)delegate startImmediately:(BOOL)startImmediately;

在startImmediately = NO的情况下,需要调用start方法开始发送请

- (void)start;
           

成为NSURLConnection的代理,最好遵守NSURLConnectionDataDelegate协议

5. NSURLConnectionDataDelegate协议中的代理方法

  • 开始接收到服务器的响应时调用

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response;

  • 接收到服务器返回的数据时调用(服务器返回的数据比较大时会调用多次)

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data;

  • 服务器返回的数据完全接收完毕后调用

- (void)connectionDidFinishLoading:(NSURLConnection *)connection;

  • 请求出错时调用(比如请求超时)

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error;

-(void)delegate
{
    //1.确定请求路径
    NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login?username=123&pwd=123&type=JSON"];
    
    //2.创建请求对象
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    
    //3.设置代理,发送请求
    //3.1
    //[NSURLConnection connectionWithRequest:request delegate:self];
    
    //3.2
    //[[NSURLConnection alloc]initWithRequest:request delegate:self];
    
    //3.3 设置代理,时候发送请求需要检查startImmediately的值
    //(startImmediately == YES 会发送 | startImmediately == NO 则需要调用start方法)
    NSURLConnection * connect = [[NSURLConnection alloc]initWithRequest:request delegate:self startImmediately:NO];
    
    //调用开始方法
    [connect start];
    
//    [connect cancel];//取消
}

#pragma mark ----------------------
#pragma mark NSURLConnectionDataDelegate
//1.当接收到服务器响应的时候调用
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    NSLog(@"%s",__func__);
}

//2.接收到服务器返回数据的时候调用,调用多次
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
     NSLog(@"%s",__func__);
    
    //拼接数据
    [self.resultData appendData:data];
}
//3.当请求失败的时候调用
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
     NSLog(@"%s",__func__);
}

//4.请求结束的时候调用
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
     NSLog(@"%s",__func__);
    
    NSLog(@"%@",[[NSString alloc]initWithData:self.resultData encoding:NSUTF8StringEncoding]);
}
           

NSURLConnection的POST

1. 常用类与GET类似

2. 比较特殊的处理方法

NSMutableURLRequest是NSURLRequest的子类,常用方法有

  • 设置请求超时等待时间(超过这个时间就算超时,请求失败)

- (void)setTimeoutInterval:(NSTimeInterval)seconds;

  • 设置请求方法(比如GET和POST)

- (void)setHTTPMethod:(NSString *)method;

  • 设置请求体

- (void)setHTTPBody:(NSData *)data;

  • 设置请求头

- (void)setValue:(NSString *)value forHTTPHeaderField:(NSString *)field;

-(void)post
{
    //1.确定请求路径
    NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login"];
    
    //2.创建可变请求对象
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    
    //3.修改请求方法,POST必须大写
    request.HTTPMethod = @"POST";
    
    //设置属性,请求超时(超过这个时间算请求失败)
    request.timeoutInterval = 10;
    
    //设置请求头User-Agent
    //注意:key一定要一致(用于传递数据给后台)
    [request setValue:@"ios 10.1" forHTTPHeaderField:@"User-Agent"];
    
    //4.设置请求体信息,字符串--->NSData
    request.HTTPBody = [@"username=520it&pwd=123&type=JSON" dataUsingEncoding:NSUTF8StringEncoding];
    
    //5.发送请求
    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
       
        //6.解析数据,NSData --->NSString
        NSLog(@"%@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
    }];
}
           

代理方法与上面block类似,除了添加request.HTTPMethod和request.HTTPBody等其余与GET的代理一样。

NSURLConnection小文件下载

#import "ViewController.h"

@interface ViewController ()<NSURLConnectionDataDelegate>
/** 注释 */
@property (nonatomic, strong) NSMutableData *fileData;
@property (nonatomic, assign) NSInteger totalSize;
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@end

@implementation ViewController

-(NSMutableData *)fileData
{
    if (_fileData == nil) {
        _fileData = [NSMutableData data];
    }
    return _fileData;
}
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    [self download3];
}

//耗时操作[NSData dataWithContentsOfURL:url]
-(void)download1
{
    //1.url
    NSURL *url = [NSURL URLWithString:@"http://img5.imgtn.bdimg.com/it/u=1915764121,2488815998&fm=21&gp=0.jpg"];
    
    //2.下载二进制数据
   NSData *data = [NSData dataWithContentsOfURL:url];
    
    //3.转换
    UIImage *image = [UIImage imageWithData:data];
}

//1.无法监听进度
//2.内存飙升
-(void)download2
{
    //1.url
   // NSURL *url = [NSURL URLWithString:@"http://imgsrc.baidu.com/forum/w%3D580/sign=54a8cc6f728b4710ce2ffdc4f3cec3b2/d143ad4bd11373f06c0b5bd1a40f4bfbfbed0443.jpg"];

    NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_01.mp4"];
    
    //2.创建请求对象
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    
    //3.发送请求
    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
       
        //4.转换
//        UIImage *image = [UIImage imageWithData:data];
//        
//        self.imageView.image = image;
        //NSLog(@"%@",connectionError);
        
        //4.写数据到沙盒中
        NSString *fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]stringByAppendingPathComponent:@"123.mp4"];
        [data writeToFile:fullPath atomically:YES];
    }];
}

//内存飙升
-(void)download3
{
    //1.url
    // NSURL *url = [NSURL URLWithString:@"http://imgsrc.baidu.com/forum/w%3D580/sign=54a8cc6f728b4710ce2ffdc4f3cec3b2/d143ad4bd11373f06c0b5bd1a40f4bfbfbed0443.jpg"];
    
    NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_01.mp4"];
    
    //2.创建请求对象
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    
    //3.发送请求
    [[NSURLConnection alloc]initWithRequest:request delegate:self];
}

#pragma mark ----------------------
#pragma mark NSURLConnectionDataDelegate
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    NSLog(@"didReceiveResponse");
    
    //得到文件的总大小(本次请求的文件数据的总大小)
    self.totalSize = response.expectedContentLength;
}

-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
   // NSLog(@"%zd",data.length);
    [self.fileData appendData:data];
    
    //进度=已经下载/文件的总大小
    NSLog(@"%f",1.0 * self.fileData.length /self.totalSize);
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
}

-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    NSLog(@"connectionDidFinishLoading");
    //4.写数据到沙盒中
    NSString *fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]stringByAppendingPathComponent:@"123.mp4"];
    
    [self.fileData writeToFile:fullPath atomically:YES];
    NSLog(@"%@",fullPath);
}
@end