天天看點

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