ASIHTTPRequest发送Get、Post请求,断点下载,上传,判断网络状态

 虽然ASIHTTPRequest已经不再更新,大多数人选择了AFNetworking,但是还是有个别公司将ASIHTTPRequest在进行封装一下或者修改一下来满足自己公司的需求,现贴上两者区别


对比
ASI AFN
更新状态 2012年10月份,已经停止更新 持续更新中,目前已更新至3.0版
介绍
ASI的直接操作对象 ASIHTTPRequest,是一个实现了了NSCopying协议的NSOperation子类。
在initialize和initWithURL:方法中初始化相关属性并配置一系列请求相关参数默认值。此外,ASIHTTPRequest还提供了一系列的实例方法用来配置请求对象。
AFN的直接操作对象AFHTTPClient,是一个实现了NSCoding和NSCopying协议的NSObject子类。AFHTTPClient是一个封装了一系列操作方法的“工具类”,处理请求的操作类是一系列单独的,基于NSOperation封装的,AFURLConnectionOperation的子类。
线程处理模式
每一个请求都由构造方法初始化一个(共享)实例,通过这个实例配置参数并发起请求。ASI最初使用delegate模式回调,在iOS SDK支持Block之后也提供了注册Block的实例方法。
ASI采取的是CFHTTP请求完成,直接回调ASIHTTPRequest的实例方法,通过储存的实例对象记录的信息完成Delegate模式或Block模式的回调。

在异步请求的处理上,ASIHTTPRequest对象初始化结束后,在startAsynchronous方法中把对象加入共享操作队列。此后, 包括创建CFHTTPMessageRef,也就是处理网络请求的主要对象(事实上是一个指向__CFHTTPMessage结构的指针),在内的所有操作都在ASIHTTPRequest对象所属的子线程中完成。
AFN的示例代码中通过一个静态方法,使用dispatch_once()的方式创建AFHTTPClient的共享实例,这也是官方建议的使用方法。在创建AFHTTPClient的初始化方法中,创建了OperationQueue并设置一系列参数默认值。在getPath:parameters:success:failure方法中创建NSURLRequest,以NSURLRequest对象实例作为参数,创建一个NSOperation,并加入在初始化发方中创建的NSOperationQueue。
以上操作都是在主线程中完成的。在NSOperation的start方法中,以此前创建的NSURLRequest对象为参数创建NSURLConnection并开启连结。
数据处理模式 ASI在这方面显得更原始,没有针对任何数据类型做特别封装,只是预留了各种接口和工具供开发者自行扩展。 AFN针对JSON、XML、PList和Image四种数据结构封装了各自处理器,开发者可以把处理器注册到操作队列中,直接在回调方法中获得格式化以后的数据。
同步请求
ASI则是直接通过调用一个startSynchronous方法。

AFN默认没有封装同步请求,如果开发者需要使用同步请求,则需要重写getPath:parameters:success:failure方法,对AFHTTPRequestOperation进行同步处理
异步回调的处理 【使用AFNetworking进行网络异步请求时,block:(void(^)代码块实际返回到UI主线程中。即使在子线程中使用AFNetWorking进行网络的异步请求,block:(void(^)代码块仍然返回到UI主线程中(AF框架,它里面已经create了异步线程 )。因此无论当前处在主线程还是子线程,异步返回均返回到UI主线程中。】
为一系列相关的请求定义一个HTTPClient,共用一个BaseURL。每次请求把URL中除BaseURL的Path部分做为参数传给HTTPClient的静态方法,并注册一个Block用于回调。
AFN则直接使用了NSOperation的completionBlock属性。
基于的底层开发框架

CFNetwork框架
使用CFnetwork而不是Cocoa框架NSURL有几点好处。CFNetwork更加专注于网络协议,而NSURL更加专注于数据访问,比如通过HTTP或者FTP传输数据。尽管NSURL的确也提供了一些可配置功能,可是CFNetwork提供的要多的多。另外NSURL还需要你使用Objective_c。如果做不到这点的话,还是应该使用CFNetwork
NSURL
【使用iOS5.0 SDK NSURLConnection:
  1、进行网络同步请求(sendSynchronousRequest)时,调用该请求接口的操作在哪个线程,同步返回的网络结果就处于哪个线程,因此通常进行网络同步请求时,为了避免阻塞UI主线程,需要在子线程中进行网络请求;
2、进行网络异步请求(sendAsynchronousRequest)时,block:(void(^)代码块实际返回到子线程中。因此,此时如需要向UI线程发送通知,则需要跳转到主线程中发送通知dispatch_async(dispatch_get_main_queue(), ^{});】
底层开发矿建介绍
CFNetwork是基于Core Foundation中CFStream的一个底层高性能网络框架,它由提供基础服务的CFSocketStream,支持HTTP协议的CFHTTP,基于CFHTTP用于身份认证的CFHTTPAuthentication和支持FTP协议的CFFTP组成。
Core Foundation框架中的CFSocket就是基于BSD Socket开发的。它几乎涵盖了BSD Socket的全部功能,更重要的是把Socket整合到事件的处理循环中。Core Founda-tion中较高层的CFStream是基于CFSocket开发的读写流支持。
如图所示,ASI是基于CFHTTP开发的一个组件;而AFN的基础——NSURL,也是基于CFNetwork开发的,也就是说ASI相比AFN更加底层。
性能对比 AFN请求优于ASI  
总结 ASI更适合已经发展了一段时间的应用,或者开发资源相对丰富的团队,因为往往这些团队(或他们的应用)已经积累了一定的经验,无论是产品上还是技术上的。需求复杂度就是在这种时候高起来,而且底层订制的需求也越来越多,此时AFN就很难满足需求,需要牺牲一定的易用性,使用ASI作为网络底层控件。 AFN适合逻辑简单的应用,或者更适合开发资源尚不丰富的团队,因为AFN的易用性要比ASI好很多,而这样的应用(或团队)对底层网络控件的定制化要求也非常低。

使用:

#import "ViewController.h"
#import "JSON.h"
#import "ASIFormDataRequest.h"
#import "Reachability.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
}

- (void)createDictionaryIfNotExists
{
    NSString *downloadPath = [NSHomeDirectory()stringByAppendingPathComponent:@"Documents/download"];
    if (![[NSFileManager defaultManager]fileExistsAtPath:downloadPath])
    {
        [[NSFileManager defaultManager]createDirectoryAtPath:downloadPath withIntermediateDirectories:YES attributes:nil error:nil];
    }
    
    NSString *tempPath = [NSHomeDirectory()stringByAppendingPathComponent:@"Documents/temp"];
    if (![[NSFileManager defaultManager]fileExistsAtPath:tempPath])
    {
        [[NSFileManager defaultManager]createDirectoryAtPath:tempPath withIntermediateDirectories:YES attributes:nil error:nil];
    }
}

//使用ASI发起GET请求
- (IBAction)getRequestClick:(UIButton *)sender
{
   NSString *urlString = @"http://api.map.baidu.com/telematics/v3/weather?location=郑州&output=json&ak=QZZGSqG9rjS1bQAAfixD9bt7&mcode=abc123";
    urlString = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
    
    //创建一个ASI的请求类,ASIHTTPRequest用于GET请求
    ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:urlString]];
    
    //设置ASI请求的代理,请求结束后,ASI就会调用相应的代理方法。
    request.delegate = self;
    //设置请求结束的回调方法(须先实现协议),如果不设定,那么ASI默认调用协议中得到的结束方法;如果设定,那么就不再调用协议方法,只调用设置的方法
    request.didFinishSelector = @selector(getRequsetFinish:);
    //设置请求的tag值
    //request.tag = 1;
    //同一个界面的多种请求,在请求完成时(1)可以通过tag值区分哪个请求完成;(2)也可以发送请求时绑定不同的请求结束调用方法。
    
    
    //startAsynchronous 异步请求(请求数据过程中不会阻塞主线程) ; startSynchronous  同步请求(请求过程会阻止主线程,如果网速慢或者请求的数据量比较大,就会导致主线程长时间处于卡死状态)
    [request startAsynchronous];
    
    //显示状态栏上的网络请求标志,YES表示圈一直在转
    //[[UIApplication sharedApplication]setNetworkActivityIndicatorVisible:YES];
}

//发送POST请求
- (IBAction)postRequest:(UIButton *)sender
{
    //ASIFormDataRequest  发送POST请求
    ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:[NSURL URLWithString:@"http://www.baidu.com"]];
    
    //setPostValue: forKey:   添加POST参数
    [request setPostValue:@"ming" forKey:@"name"];
    [request setPostValue:@"20" forKey:@"age"];
    
    request.delegate = self;
    request.didFinishSelector = @selector(postRequestFinish:);
    
    [request startAsynchronous];
}

//下载文件
- (IBAction)downloadFileClick:(UIButton *)sender
{
    //如果正在下载,不再发送下载请求
    if (_downloadRequest)
    {
        return;
    }
    
    NSURL *url = [NSURL URLWithString:@"http://localhost:8080/FileUploadServer/net.zip"];
    _downloadRequest = [ASIHTTPRequest requestWithURL:url];
    
    //设置下载路径,设置过下载路经之后,ASI就会把这次请求当作下载请求,自动把收到的数据存入路径文件,request.responseData中就不会在自动拼数据。设置的路径文件夹必须保证存在(不会自动创建)。
    [self createDictionaryIfNotExists];
    NSString *path = [NSHomeDirectory()stringByAppendingPathComponent:@"Documents/download/a.zip"];
    _downloadRequest.downloadDestinationPath = path;
    
    _downloadRequest.delegate = self;
    //设置下载进度代理,每当下载到新数据时,ASI就会调用代理对象的协议方法
    _downloadRequest.downloadProgressDelegate = self;
    _downloadRequest.didFinishSelector = @selector(downloadRequestFinish:);
    
    //实现断点下载
    //设置文件的临时下载路径 (必须保证存在)   temporary,临时的
    _downloadRequest.temporaryFileDownloadPath = [NSHomeDirectory()stringByAppendingPathComponent:@"Documents/temp/a.zip"];
    //设置是否可以断点续传    Resume ,继续
    _downloadRequest.allowResumeForFileDownloads = YES;
    
    [_downloadRequest startAsynchronous];
}

//暂停下载
- (IBAction)stopDownload:(UIButton *)sender
{
    [_downloadRequest cancel];
    _downloadRequest = nil;
}

//上传文件
- (IBAction)uploadFileClick:(UIButton *)sender
{
    ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:[NSURL URLWithString:@"http://localhost:8080/FileUploadServer/UploadServlet"]];
    
    //如果上传小文件,setPostBody  直接把文件放入请求体即可
    //[request setPostBody:data];
    
    //把一个文件的数据设置到请求体中(上传大文件,直接存入硬盘)
    NSString *path = [[NSBundle mainBundle]pathForResource:@"file" ofType:@"zip"];
    [request setPostBodyFilePath:path];
    
    //setShouldStreamPostDataFromDisk  设置是否使用输入流从磁盘中读取数据到请求体,对于大文件必须使用输入流读入。
    [request setShouldStreamPostDataFromDisk:YES];
    
    //设置上传进度代理
    request.uploadProgressDelegate = self;
    
    request.delegate = self;
    request.didFinishSelector = @selector(uploadRequestFinish:);
    [request startAsynchronous];
}

//判断当前网络状态
- (IBAction)isNetWorkClick:(UIButton *)sender
{
    //Reachability  能够判断当前的网络状态
    Reachability *reach = [Reachability reachabilityForInternetConnection];
    switch (reach.currentReachabilityStatus)
    {
        case kNotReachable:
            _netWorkLabel.text = @"没有网络";
            break;
        case kReachableViaWWAN:
            _netWorkLabel.text = @"手机网络";
            break;
        case kReachableViaWiFi:
            _netWorkLabel.text = @"WIFI网络";
        default:
            break;
    }
    
    //网络状态发生变化时的通知
    //extern NSString *const kReachabilityChangedNotification
}

//ASI请求失败时调用
- (void)requestFailed:(ASIHTTPRequest *)request
{
    NSLog(@"ASI请求失败原因:%@",request.error);
}

//ASI请求成功时调用
- (void)requestFinished:(ASIHTTPRequest *)request
{
    //request.responseData     请求得到的数据
    //request.responseString   请求数据按照UTF8转换的字符串
    //NSLog(@"%@",request.responseString);
    
    //使用 SBJSON 解析数据
    NSDictionary *dic = request.responseString.JSONValue;
    NSLog(@"%@",dic);
}

//请求数据时调用,如果实现了这个方法,ASI就不再自动拼接数据
//- (void)request:(ASIHTTPRequest *)request didReceiveData:(NSData *)data
//{
//    NSLog(@"收到数据了");
//}

- (void)getRequsetFinish:(ASIHTTPRequest *)request
{
    NSLog(@"自己设定的协议方法\n%@",request.responseString);
}

- (void)postRequestFinish:(ASIFormDataRequest *)request
{
    NSLog(@"%@",request.responseString);
}

- (void)downloadRequestFinish:(ASIHTTPRequest *)request
{
    NSLog(@"下载完成");
    _downloadRequest = nil;
}

//每当进度更新时调用
- (void)setProgress:(float)newProgress
{
    _progressVIew.progress = newProgress;
}

- (void)uploadRequestFinish:(ASIFormDataRequest *)request
{
    NSLog(@"上传完成");
}

 

你可能感兴趣的:(ASIHTTPRequest)