zoukankan      html  css  js  c++  java
  • ASIHTTPRequest官方文档(一)

    1.创建并运行一个请求

    1.1 创建一个同步请求

    创建一个同步请求是使用ASIHTTPRequest的最简单的方式。发送消息startSynchronous会在同一个线程中执行这个请求,并且当请求结束的时候会返回控制权(成功或者其它的情况)。

    通过error属性检查问题。

    调用方法responseString从返回结果中获取字符串,不要使用这个方法获取二进制数据,使用方法responseData获得一个NSData对象。对于大的文件,设置你的请求的downloadDestinationPath属性用于下载文件。

          - (IBAction)grabURL:(id)sender

          {

                   NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"];

                   ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];

                   [request startSynchronous];

                   NSError *error = [request error];

                   if (!error) {

                           NSString *response = [request responseString];

                   }

            }

    注意:一般来说,你应该优先使用异步请求而不是同步请求。当你在主线程中使用ASIHTTPRequest的同步请求时,你的应用的用户界面会被锁定并且在整个网络请求期间不可用。

    1.2 创建一个异步请求

    做与上一个例子相同的事情,但是这个请求在后台运行。

           - (IBAction)grabURLInBackground:(id)sender

          {

                  NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"];

                  ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];

                  [request setDelegate:self];

                  [request startAsynchronous];

           }

           - (void)requestFinished:(ASIHTTPRequest *)request

           {

                  // Use when fetching text data

                  NSString *responseString = [request responseString];

                  // Use when fetching binary data

                  NSData *responseData = [request responseData];

           }

           - (void)requestFailed:(ASIHTTPRequest *)request

           {

                  NSError *error = [request error];

           }

    我们设置了请求的delegate属性,所以当请求完成或失败时,我们能够接到通知。

    这是创建异步请求的最简单的方式,它会在一个位于后台的全局的NSOperationQueue中运行。为了实现更多复杂的操作(例如跟踪多个请求的处理过程),你可能想创建自己的queue,这是下面将要讲到的。

    1.3 使用blocks

    从1.8版本起,我们可以在支持它们的平台上通过使用blocks完成上面例子的功能。

           - (IBAction)grabURLInBackground:(id)sender

          {

                  NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"];

                  __block ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];

                  [request setCompletionBlock:^{

                        // Use when fetching textdata

                        NSString *responseString = [request responseString];

                        // Use when fetching binarydata

                        NSData *responseData = [request responseData];

                  }];

                  [request setFailedBlock:^{

                        NSError *error = [request error];

                  }];

                  [request startAsynchronous];

           }

        注意当我们声明这个请求时标识符__block的使用,这是非常重要的!它告诉这个block不要retain这个请求,因为这个请求总是retain这个block,这样就避免了一个retain-cycle 。

    1.4 使用队列

    这个例子做相同的事情,但是这次我们为我们的请求创建一个NSOperationQueue。

    使用你创建的NSOperationQueue(或者下面讲到的ASINetworkQueue),就可以对异步请求进行更多的控制。当使用一个queue的时候,只有一定数量的请求同时运行。如果你向一个队列中添加的请求多于属性maxConcurrentOperationCount指定的数量,多出的请求会等到其它的请求结束才能开始运行。

           - (IBAction)grabURLInTheBackground:(id)sender

           {

                  if (![self queue]) {

                        [self setQueue:[[[NSOperationQueue alloc] init] autorelease]];

                  }

                  NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"];

                  ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];

                  [request setDelegate:self];

                  [request setDidFinishSelector:@selector(requestDone:)];

                  [request setDidFailSelector:@selector(requestWentWrong:)];

                  [[self queue] addOperation:request]; //queue is anNSOperationQueue

           }

           - (void)requestDone:(ASIHTTPRequest *)request

           {

                  NSString *response = [request responseString];

            }

            - (void)requestWentWrong:(ASIHTTPRequest *)request

           {

                  NSError *error = [request error];

           }

           在上面的例子中,’queue’是我们控制器的一个retainedNSOperationQueue属性。

           我们设置自定义的selectors,它们会在请求成功或失败后被调用。如果你不设置这些,默认的(requestFinished:和requestFailed:)会向前面的例子中那样被使用。

    1.5 在代理方法中处理多个请求的成功和失败状态

    如果你需要处理多个请求的成功和失败的状态,你可以有几种选择:

    1.           如果你的请求是相同的类型,但是你想区分它们,你可以用自定义的数据设置每个请求的字典类型的属性userInfo,这样你就可以在请求的成功或失败的代理方法中读取设置的值,通过这些值区分不同的请求。更简单的一种方式,你可以设置请求的tag属性。这两种属性是提供给你使用的,它们不会被发送到服务端。

    2.           对于每个请求,如果你需要一个完全不同的方式处理成功或失败的返回结果,你可以针对每个请求设置不同的setDidFinishSelector和setDidFailSelector。

    3.           对于更复杂的情况,或者说如果你想在后台解析返回结果,可以这堆每种类型的请求,创建ASIHttpRequest的一个最小子类,并且重载方法requestFinished:和failWithError:。

    注意:最好避免在代理方法中通过请求的URL区分不同的请求,因为当重定向的时候URL属性会改变。如果你真的想使用请求的URL,可以使用[request originalURL],这样总会是第一次请求的url。

    1.6 关于ASINetworkQueues

        ASINetworkQueue是类NSOperationQueue的子类,它提供了一些额外的功能。

    它主要的目的是使你能够跟踪整个queue的上传和下载的过程。

    另外,ASINetworkQueues提供了一些额外的代理方法:

    l   requestDidStartSelector

        队列中的每个请求开始执行的时候调用这个方法。你可以使用它作为”设置你添加到queue的请求的代理方法并指定这个请求的didStartSelector”的替代方法。

    l   requestDidReceiveResponseHeaderSeletor

    当队列中的一个请求收到服务端回复的请求头时被调用。对于大数据量的下载,这个会在真正的下载完成之前被调用。你可以使用这个作为“设置你添加到queue中的请求的代理并且指定请求的didFailSelector”的一个替代方案。

    l   requestDidFinishSelector

        当队列中一个请求成功时被调用。你可以使用这个作为“设置你添加到队列中请求的代理并指定一个didFinishSelector”的一个替代方案。

    l    requestDidFailSelector

        当队列中一个请求失败时被调用。你可以使用这个作为“设置你添加到队列中请求的代理并指定一个didFailSelector”的一个替代方案。

    l     queueDidFinishSelector

    当整个队列完成时才被调用,不管单个的请求是成功还是失败。

    要使用这些,可以设置队列的代理(而不是设置请求的代理)为实现这些selector的控制器。

           ASINetworkQueues的使用和NSOperationQueues有一点不同,就是添加到ASINetworkQueues的请求并不会马上开始执行。当使用一个ASINetworkQueue时,添加你想运行的操作,然后调用[queue go]。当你开启一个队列并打开“进度控制”标志时,它首先会为队列中的每个请求发送一个获取头部信息的请求,以获得要下载的数据的大小。一旦队列获得了要下载的大小,它能准确的显示整个下载过程,真正的下载也会开始。

    注意:

           当你添加一个请求到一个已经开始的ASINetworkQueue中会发生什么?当你使用ASINetworkQueue跟踪一些请求的整个进展,当添加一个新的请求到队列,只有新的请求开始运行的时候,整个队列会进入后台运行。当队列开始运行的时候后,新添加的请求不会再请求头部信息,所以当你一次添加很多请求到一个已经开始运行的队列,整个进度不会立刻更新。

    如果一个队列已经开始运行,你不需要再调用[queuego]。

        当ASINetworkQueue中的一个请求执行失败时,队列默认会取消所有的请求。你可以通过 [queue setShouldCancelAllRequestsOnFailure:NO]

    取消这个属性。

     ASINetworkQueue只能运行ASIHTTPRequest操作,它们不能用于一般的操作。添加一个非ASIHTTPRequest的NSOperation会触发一个异常。

         注意:这个一个完整的演示基本的创建和使用ASINetworkQueue例子:http://gist.github.com/150447

    1.7 取消一个异步请求

           调用[request cancel]取消一个异步请求(一个以[ [request startAsynchronous] ]开始的请求或者你创建的运行在队列中的请求)。注意你不能取消一个同步请求。

    当你取消一个请求,这个请求会把这个当作一个错误,会调用请求的代理或者队列的代理的失败处理方法。如果你不希望这个行为,在取消一个请求之前设置这个请求的代理为nil或者使用方法clearDelegatesAndCancel取消请求。

               //Cancels an asynchronous request

               [requestcancel]

               //Cancels an asynchronous request, clearing all delegates and blocks first

                [requestclearDelegatesAndCancel];

    使用一个ASINetworkQueue时,当你取消了队列中的一个请求,那么队列中所有的请求都会被取消除非你设置了队列的属性shouldCancelAllRequestsOnFailure为NO(YES是默认值)。

            // When a request inthis queue fails or is cancelled, other requests will continue to run

            [queuesetShouldCancelAllRequestsOnFailure:NO];

            // Cancel all requestsin a queue

            [queue cancelAllOperations];

    1.8 当一个请求将要结束之前安全的处理即将被销毁的代理

    请求不retain它们的代理,所以当请求正在执行的时候你的代理可能会被释放掉,清除请求的代理属性是至关重要的。在大多数情况下,如果你的代理将要被释放,你也不再关心这个请求的状态,所以你可能也想取消这个请求。

        在下面的例子中,我们的控制器有一个属性为retain的ASIHTTPRequest类型的实例变量。我们在方法delloc的实现中调用请求的clearDelegatesAndCancel方法,正好在在释放这个请求之前。

           // Ddealloc method for ourcontroller

           - (void)dealloc

           {

                  [requestclearDelegatesAndCancel];

                   [requestrelease];

                   ...

                  [superdealloc];

           }

    2.发送数据

    2.1 设置请求头

                  ASIHTTPRequest *request =[ASIHTTPRequest requestWithURL:url];

                  [requestaddRequestHeader:@"Referer"value:@"http://allseeing-i.com/"];

    2.2 使用ASIFormDataRequest发送一个POST请求

        可以使用ASIFormDataRequest发送与网页格式兼容的POST请求。以application/x-www-form-urlencoded格式POST数据或者以multipart/form-data格式POST二进制数据或文件。如果需要文件中的数据会从硬盘读取,所以可以提交大的文件,只要你的Web服务器支持处理它们。

                  ASIFormDataRequest *request = [ASIFormDataRequestrequestWithURL:url];

                  [request setPostValue:@"Ben"forKey:@"first_name"];

                  [request setPostValue:@"Copsey"forKey:@"last_name"];

                  [request setFile:@"/Users/ben/Desktop/ben.jpg"forKey:@"photo"];

           ASIFormDataRequest会自动检测通过方法setFile:forKey添加到POST的文件的mine类型,并且把这个添加到mime头中发送到服务端。如果你愿意,你可以使用更长的形式代替这种方式:

                  ASIFormDataRequest *request = [ASIFormDataRequestrequestWithURL:url];

                  // Upload a file on disk

                  [request setFile:@"/Users/ben/Desktop/ben.jpg" withFileName:@"myphoto.jpg"andContentType:@"image/jpeg" forKey:@"photo"];

                  // Upload an NSData instance

                  [request setData:imageData withFileName:@"myphoto.jpg"andContentType:@"image/jpeg" forKey:@"photo"];

           你可以使用add接口针对一个参数发送多个值:

                  ASIFormDataRequest *request = [ASIFormDataRequestrequestWithURL:url];

                  [request addPostValue:@"Ben" forKey:@"names"];

                  [request addPostValue:@"George"forKey:@"names"];

                  [request addFile:@"/Users/ben/Desktop/ben.jpg"forKey:@"photos"];

                  [requestaddData:imageData withFileName:@"george.jpg"andContentType:@"image/jpeg" forKey:@"photos"];

           查看ASIFormDataRequest.h获取向POST添加参数的全部的方法列表。

    2.3 PUT请求和自定义POSTs

        如果你想通过PUT发送数据,或者想通过POST但是想自己创建POST包体,可以使用appendPostData:or appendPostDataFromFile:。

                  ASIHTTPRequest *request =[ASIHTTPRequest requestWithURL:url];

                  [request appendPostData:[@"Thisis my data" dataUsingEncoding:NSUTF8StringEncoding]];

                  // Default becomes POST when you useappendPostData: / appendPostDataFromFile: / setPostBody:

                  [requestsetRequestMethod:@"PUT"];

           如果你想发送大量的数据但是不想使用ASIFormDataRequest,可以看下面将要介绍的“informationon streaming post bodies from disk ”。

    3.下载数据

    3.1 直接把回复内容下载到文件

    如果你请求的资源非常的大,你可以直接下载到文件以节省内存。这样的话,ASIHTTPRequest不需要一下子在内存中维护所有的回复内容。

                  ASIHTTPRequest*request = [ASIHTTPRequest requestWithURL:url];

                  [requestsetDownloadDestinationPath:@"/Users/ben/Desktop/my_file.txt"];

           当你使用属性downloadDestinationPath下载数据到一个文件时,在请求处理过程中数据会保存在一个临时文件中。当请求完成时,下面两个事情的其中一个会发生:

    l   如果数据是gzip压缩的(查看gzip压缩数据),被压缩的文件会解压到downloadDestinationPath指定的路径下,临时文件会被删除。

    l   如果数据不是压缩的,临时文件会被移动到downloadDestinationPath指定的路径下,并会覆盖同名的文件。

    注意:如果回复的包体是空的,文件不会被创建。如果一个请求可能会返回一个空的包体,再你做任何尝试之前,请先检查下文件是否存在。

    3.2 处理到来的回复数据

           如果你需要处理到来的包体数据(比如:当数据还在下载的时候使用“流解析“解析回复的数据),实现代理的request:didReceiveData:方法(查看ASIHTTPRequestDelegate.h)。注意当你这样做的时候,ASIHTTPRequest不会填充responseData,也不会把回复数据写入到downloadDestinationPath指定的路径,如果你需要你必须自己保存回复的数据。

    3.3 读取HTTP状态码

    对于大部分HTTP状态码,ASIHTTPRequest不会做任何特殊的事情(除了重定向和认证状态码,查看下面的内容获取更多信息),因此需要你查找问题并确认你是否操作得当。

                  ASIHTTPRequest *request =[ASIHTTPRequest requestWithURL:url];

                  [request startSynchronous];

                  int statusCode = [requestresponseStatusCode];

                  NSString *statusMessage = [request responseStatusMessage];

    3.4 读取回复的头部信息

                  ASIHTTPRequest*request = [ASIHTTPRequest requestWithURL:url];

                  [requeststartSynchronous];

                  NSString*poweredBy = [[request responseHeaders]objectForKey:@"X-Powered-By"];

                  NSString *contentType = [[requestresponseHeaders] objectForKey:@"Content-Type"];

    3.5 处理文本编码

    ASIHTTPRequest会尝试从头部的Content-Type字段读取接收到的数据的文本编码,如果它发现一个文本编码,它会设置字段responseEncoding为一个合适的 NSStringEncoding。如果它在头部字段没有发现一个文本编码,它会使用字段defaultResponseEncoding的默认值(这个字段默认值为NSISOLatin1StringEncoding)。

        当你调用[request responseString], ASIHTTPRequest会创建一个字符串,并尝试以responseEncoding指定的编码方式把接收到的数据转化到创建的字符串中。

    3.6 处理重定向

    ASIHTTPRequest会自动的重定向到一个新的URL当它遇到下面的一个HTTP状态码,假设一个本地的头已经发送:

    l   301 Moved Permanently

    l   302 Found

    l   303 See Other

           当重定向发生时, responsedata的值(例如responseHeaders / responseCookies / responseData / responseString )会是从最后的地址接收到的值。

    重定向的url的Cookies会存储到一个全局的cookie存储中,适当的时候会在一个重定向请求中表示服务器。

        你可以通过设置请求的属性shouldRedirect为NO关闭重定向。

    注意:

           默认情况下,自动重定向只针对GET请求(没有消息体)。指定301和302重定向需要使用最初的方法符合多数浏览器的工作方式,不是HTTP协议特定的。

    为了保存最初的方法(包括请求体)

    针对301和302重定向,为了保存最初的方法(包括请求体),需要在请求开始执行之前,设置请求的属性shouldUseRFC2616RedirectBehaviour为YES。

  • 相关阅读:
    【读书笔记】深入理解计算机系统
    快速排序
    列表查找的两种方法
    冒泡排序、选择排序、插入排序
    堆排序
    supervisor进程管理
    redis-主从复制
    redis-淘汰策略
    URI和URL
    python爬虫之xpath的基本使用
  • 原文地址:https://www.cnblogs.com/zhwl/p/2591752.html
Copyright © 2011-2022 走看看