ASIHTTPRequest 使用指南(中文版)


ASIHTTPRequest 使用指南(中文版) www.devdiv.com 翻译整理 DevDiv 翻译:dymx101 1 DevDiv 校对:dymx101 DevDiv 编辑:BeyondVincent 版本 1.0 | 2011 年 9 月 某 日 ASIHTTPRequest 使用指南(中文版) 版本 1.0 翻译时间:2011 年 9 月 DevDiv 翻译:dymx101 DevDiv 校对:dymx101 DevDiv 编辑:BeyondVincent ASIHTTPRequest 使用指南(中文版) www.devdiv.com 翻译整理 DevDiv 翻译:dymx101 2 DevDiv 校对:dymx101 DevDiv 编辑:BeyondVincent 版本 1.0 | 2011 年 9 月 某 日 写在前面 目前,移动开发被广大的开发者们看好,并大量的加入移动领域的开发。 鉴于以下原因:  国内的相关中文资料缺乏  许多开发者对 E 文很是感冒  电子版的文档利于技术传播和交流 DevDiv.com 移动开发论坛特此成立了翻译组,翻译组成员具有丰富的移动开发经验和英 语翻译水平。组员们利用业余时间,把一些好的相关英文资料翻译成中文,为广大移动开发 者尽一点绵薄之力,希望能对读者有些许作用,在此也感谢组员们的辛勤付出。 关于 DevDiv DevDiv 已成长为国内最具人气的综合性移动开发社区 更多相关信息请访问 DevDiv 移动开发论坛。 技术支持 首先 DevDiv 翻译组对您能够阅读本文以及关注 DevDiv 表示由衷的感谢。 在您学习和开发过程中,或多或少会遇到一些问题。DevDiv 论坛集结了一流的移动专 家,我们很乐意与您一起探讨移动开发。如果您有什么问题和技术需要支持的话,请访问网 站 www.devdiv.com 或者发送邮件到 BeyondVincent@DevDiv.com,我们将尽力所能及的帮助 你。 关于本文的翻译 感谢会员 dymx101 对本文的翻译和校对。才使本文与读者尽快见面。由于书稿内容多, 我们的知识有限,尽管我们进行了细心的检查,但是还是会存在错误,这里恳请广大读者批 评指正,并发送邮件至 BeyondVincent@devdiv.com,在此我们表示衷心的感谢。 原文地址:http://allseeing-i.com/ASIHTTPRequest/How-to-use 帖子链接: ASIHTTPRequest 使用指南---<<翻译稿>>---连载 ... ASIHTTPRequest 使用指南(中文版) www.devdiv.com 翻译整理 DevDiv 翻译:dymx101 3 DevDiv 校对:dymx101 DevDiv 编辑:BeyondVincent 版本 1.0 | 2011 年 9 月 某 日 目录 写在前面 2 关于 DevDiv 2 技术支持 2 关于本文的翻译 2 目录 3 第 1 章 创建和运行请求 5 1.1. 创建一个同步请求 5 1.2. 创建一个异步请求 5 1.3. 使用程序块(blocks) 6 1.4. 使用队列 6 1.5. 在委托方法中处理多个请求的成功和失败 7 1.6. 关于 ASINetworkQueues 7 1.7. 取消一个异步请求 8 1.8. 安全处理委托在请求完成前释放的情况 8 第 2 章 发送数据 10 2.1. 发送请求头 10 2.2. 用 ASIFormDataRequest 发送一个表单 10 2.3. put 方法和自定义 post 10 第 3 章 下载数据 12 3.1. 将响应数据直接下载为文件 12 3.2. 处理收到的响应数据 12 3.3. 读取 HTTP 状态码 12 3.4. 读取响应头 12 3.5. 处理文本编码 12 3.6. 处理重定向 13 第 4 章 跟踪进度 14 4.1. 介绍 14 4.2. 跟踪单个请求的下载进度 14 4.3. 跟踪一组请求的下载进度 14 4.4. 跟踪单个请求的上传进度 15 4.5. 跟踪一组请求的上传进度 15 4.6. 精确进度 vs 简单进度 15 4.6.1. 简单请求 16 4.6.2. 精确进度 16 4.7. 自定义进度跟踪 16 第 5 章 处理 http 验证 17 5.1. 介绍 17 5.2. 在 url 中指定用户名和密码 17 5.3. 设置请求的用户名和密码 17 5.4. 在钥匙串(keychain)中储存证书 17 5.5. 在会话中储存 17 5.6. NTML 验证 17 5.7. 使用委托来提供证书 18 5.8. 使用内置验证对话框(目前仅 ios 可用) 18 5.9. 在服务器要求之前提供证书 19 第 6 章 Cookies 20 6.1. 持久化 cookies 20 6.2. 手工处理 cookie 20 第 7 章 处理压缩的响应,以及压缩请求 body 21 ASIHTTPRequest 使用指南(中文版) www.devdiv.com 翻译整理 DevDiv 翻译:dymx101 4 DevDiv 校对:dymx101 DevDiv 编辑:BeyondVincent 版本 1.0 | 2011 年 9 月 某 日 7.1. 使用 gzip 来处理压缩的响应数据 21 7.2. 联机解压 gzip 响应包 21 7.3. 使用 gzip 来压缩请求 body 22 第 8 章 恢复被打断的下载 23 8.1. 如何恢复下载 23 第 9 章 直接从磁盘流式请求 body 24 9.1. 介绍 24 9.2. ASIFormDataRequests 24 9.3. 常规的 ASIHTTPRequest 24 第 10 章 使用下载缓存 25 10.1. 介绍 25 10.2. 关于缓存策略 25 10.3. 关于存储策略 26 10.4. 其他缓存特性 26 10.5. 写你自己的缓存 27 第 11 章 节约带宽 28 11.1. 如何使用宽带限制 28 第 12 章 客户端证书支持 29 12.1. 如何使用客户端证书 29 第 13 章 同代理一起工作 30 13.1. 介绍 30 13.2. 验证代理 30 13.3. 手动指定代理的证书 30 13.4. 使用委托来询问代理证书 30 13.5. 使用内置验证对话框(目前仅 ios) 30 第 14 章 其他特性 32 14.1. 自定义用户代理 32 14.2. 在 ios 中程序进入后台时继续请求 32 14.3. 监视网络活动 32 14.4. 禁用自动更新网络活动指示器(仅 ios) 32 14.5. 当请求超时自动重试 32 14.6. 配置持续连接(persistent connection) 32 14.7. 强制使用 http 1.0 33 14.8. 禁用安全证书验证 33 第 15 章 调试选项 34 15.1. ASIHTTPRequest 调试标志信息 34 ASIHTTPRequest 使用指南(中文版) www.devdiv.com 翻译整理 DevDiv 翻译:dymx101 5 DevDiv 校对:dymx101 DevDiv 编辑:BeyondVincent 版本 1.0 | 2011 年 9 月 某 日 第 1 章 创建和运行请求 1.1. 创建一个同步请求 这是最简单的用法,发送 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 的同步方法,程序的 ui 在请求过程中将被锁定而无法响应。 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 { // 获得文本数据 NSString*responseString =[request responseString]; // 获得二进制数据 NSData*responseData =[request responseData]; } -(void)requestFailed:(ASIHTTPRequest*)request ASIHTTPRequest 使用指南(中文版) www.devdiv.com 翻译整理 DevDiv 翻译:dymx101 6 DevDiv 校对:dymx101 DevDiv 编辑:BeyondVincent 版本 1.0 | 2011 年 9 月 某 日 { NSError*error =[request error]; } 注意我们设置请求的委托,这样就能在请求完成或失败时得到通知。 这是创建异步请求最简单的方式,他会运行于场景后面的一个全局的 NSOperationQueue 中,对于更复杂 的操作,例如在多个请求中追踪进展,你可能想要创建自己的队列,下一步我们会谈谈这个。 1.3. 使用程序块(blocks) 对于 v1.8,我们可以在支持程序块的平台使用他们: -(IBAction)grabURLInBackground:(id)sender { NSURL*url=[NSURL URLWithString:@"http://allseeing-i.com"]; __block ASIHTTPRequest*request =[ASIHTTPRequest requestWithURL:url]; [request setCompletionBlock:^{ // Use when fetching text data NSString*responseString =[request responseString]; // Use when fetching binary data NSData*responseData =[request responseData]; }]; [request setFailedBlock:^{ NSError*error =[request error]; }]; [request startAsynchronous]; } 注意:在我们声明请求时,用到了__block 限定语,这很重要!它告诉 block 不要保留请求,来防止一个 保留循环(retain-cycle),因为请求总会保留 block. 1.4. 使用队列 这个例子做同样的事,不同的是,我们为自己的请求创建了 NSOperationQueue。 使用一个 NSOperationQueue 或者 ASINetworkQueue,你能更有效的控制异步请求。我们使用一个请求, 只有一定数量的请求能同时运行。如果你添加多于 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 an NSOperationQueue } ASIHTTPRequest 使用指南(中文版) www.devdiv.com 翻译整理 DevDiv 翻译:dymx101 7 DevDiv 校对:dymx101 DevDiv 编辑:BeyondVincent 版本 1.0 | 2011 年 9 月 某 日 -(void)requestDone:(ASIHTTPRequest*)request { NSString*response =[request responseString]; } -(void)requestWentWrong:(ASIHTTPRequest*)request { NSError*error =[request error]; } 在上面的例子中,'queue'是控制器的一个保留的 NSOperationQueue 属性。 我们设置自定义的 selector 处理成功或失败的回调。如果你不设置这些,默认的 requestFinished 和 requestFailed 将被使用,就像在之前的例子中一样。 1.5. 在委托方法中处理多个请求的成功和失败 如果你需要处理许多不同类型的请求,你有几个选择: 1. 如果你的请求都属于一个大的范围,你又想区别他们,可以设置请求的 userInfo 字典属性,填入你的自 定义数据,你就可以在委托方法中读取了。在更简单的用例中,你可以简单的设置 tag 属性。这些属性都是给 你自己用的,不会发送到服务器。 2. 如果你处理完全不同的请求,为每个请求设置不同的 setDidFinishSelector / setDidFailSelector。 3. 对更复杂的情况,或者你想在后台解析响应数据,可以为每个请求类型创建一个 ASIHTTPRequest 的子 类,然后重载 requestFinished: 和 failWithError: 。 注意:最好避免在委托方法中,用 url 来区分不同的请求,因为 url 属性在重定向时会改变。如果你真的 真的想用的话,请用[request originalURL] 代替,这个将总是记录第请求连接时的首个 url。 1.6. 关于 ASINetworkQueues ASINetworkQueues 是 NSOperationQueue,它提供了额外的功能。 它的主要目的是追踪整个队列上传或下载的进度。 ASINetworkQueues 提供了一些额外的委托方法 selector。 requestDidStartSelector 每当队列中的一个请求开始运行时调用。你可以使用这个作为 didStartSelector 的替代方法,为你加到队列 的请求设置一个委托。 requestDidReceiveResponseHeadersSelector 每当队列中的一个请求从服务器得到响应头时调用。对于大的下载,这个 selector 有时在请求实际完成前 执行。 你可以使用它作为对 didReceiveResponseHeadersSelector 的替代。 requestDidFinishSelector 每当队列中的一个请求完成时调用。可以使用它作为对 didFinishSelector 的替代。 ASIHTTPRequest 使用指南(中文版) www.devdiv.com 翻译整理 DevDiv 翻译:dymx101 8 DevDiv 校对:dymx101 DevDiv 编辑:BeyondVincent 版本 1.0 | 2011 年 9 月 某 日 requestDidFailSelector 每当队列中的请求失败时调用,可作为 didFailSelector 的替代。 queueDidFinishSelector 当队列完成时调用,不管单个请求成功或失败。 使用以上 selector,要将队列的委托,而不是请求的委托,设置到实现这些 selector 所代表的方法的控制器。 ASINetworkQueues 工作起来和 NSOperationQueues 稍有不同,加到其中的请求不会立刻运行,当使用 ASINetworkQueue 时,添加你想运行的所有请求,然后调用[queue go]。当你启动一个队列,将精确进度 (accurate progress)打开时,他会首先为队列中所有的 get 请求执行一个 head 请求,来得到将要下载数据的总体 尺寸。获得此数据后,它就能准确的显示总体进度,然后真实的请求才会开始。 问题:当你向一个运行中的 ASINetworkQueue 加入一个请求时发生了什么事情? 回答:如果你使用 ASINetworkQueue 来追踪几个请求的总体进度,整体进度只会在哪个请求开始执行时, 才会将它计算在内。ASINetworkQueue 不会在运行中,当加入请求后执行 head 请求,所以如果你立刻向运行 的队列加入许多请求,总体进度不会立刻更新。 如果队列已经运行,你不需要再次调用[queue go]。 当 ASINetworkQueue 中的一个请求失败,队列默认的将取消所有其他的请求。你可以调用[queue setShouldCancelAllRequestsOnFailure:NO].来关闭这一行为。 ASINetworkQueues 只 能 执 行 ASIHTTPRequest 操作,而不能用于一般操作,尝试添加一个非 ASIHTTPRequest 的 NSOperation 将产生一个异常。 提示:这里有一个创建和使用 ASINetworkQueue 的完整例子: http://gist.github.com/150447 1.7. 取消一个异步请求 为了取消一个异步请求,可以调用[request cancel],不管该请求是用[request startAsynchronous] 启动的,还 是在你创建的队列中运行。注意你不能取消一个同步请求。 注意,当你取消一个请求,请求会将之视为一个错误,然后会调用你的委托或者队列的失败委托方法。如 果你不想这种事发生,在取消之前将委托设为 nil,或者使用 clearDelegatesAndCancel 作为代替。 // Cancels an asynchronous request [request cancel] // Cancels an asynchronous request, clearing all delegates and blocks first [request clearDelegatesAndCancel]; 当使用一个 ASINetworkQueue 时,你取消其中一个请求,所有其他的请求也会被取消,除非队列的 shouldCancelAllRequestsOnFailure 为 no, 默认为 yes。 // When a request in this queue fails or is cancelled, other requests will continue to run [queue setShouldCancelAllRequestsOnFailure:NO]; // Cancel all requests in a queue [queue cancelAllOperations]; 1.8. 安全处理委托在请求完成前释放的情况 请求不会保留他们的委托,所以如果你的委托有机会在请求运行时释放的话,你能及时清理请求的委托属 性是至关重要的。在大多数情况下,如果你的委托将要释放,你大概也想取消请求,因为你不再关心请求的状 态。 ASIHTTPRequest 使用指南(中文版) www.devdiv.com 翻译整理 DevDiv 翻译:dymx101 9 DevDiv 校对:dymx101 DevDiv 编辑:BeyondVincent 版本 1.0 | 2011 年 9 月 某 日 在下面的例子中,控制器有一个保存于保留实例变量中的 ASIHTTPRequest 对象。我们在其 dealloc 实现 中调用 clearDelegatesAndCancel 方法,在我们释放请求的引用之前: // Ddealloc method for our controller - (void)dealloc { [request clearDelegatesAndCancel]; [request release]; ... [super dealloc]; } ASIHTTPRequest 使用指南(中文版) www.devdiv.com 翻译整理 DevDiv 翻译:dymx101 10 DevDiv 校对:dymx101 DevDiv 编辑:BeyondVincent 版本 1.0 | 2011 年 9 月 某 日 第 2 章 发送数据 2.1. 发送请求头 ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url]; [request addRequestHeader:@"Referer" value:@"http://allseeing-i.com/"]; 2.2. 用 ASIFormDataRequest 发送一个表单 要以兼容 web 页 表 单 的 方 式 发 送 post 数 据 , 可 以 使 用 ASIFormDataRequest 的子类。数据以 ‘application/x-www-form-urlencoded’格式寄出,或者用‘multipart/form-data’格式上传二进制数据或文件。 文件中的数据按照需要从磁盘读取,所以发送大文件是没问题的,只要你的 web 服务器设置了如何处理他们。 ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL: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:添加文件时将自动侦测文件的 mime 类型(ios3.0 之后),并包含 这个到发送到服务器的 mime 头部中。如果你愿意,你可以使用更长的重载形式: ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL: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 api: ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url]; [request addPostValue:@"Ben" forKey:@"names"]; [request addPostValue:@"George" forKey:@"names"]; [request addFile:@"/Users/ben/Desktop/ben.jpg" forKey:@"photos"]; [request addData:imageData withFileName:@"george.jpg" andContentType:@"image/jpeg" forKey:@"photos"]; 参考 ASIFormDataRequest.h,了解添加到你 post 的参数的所有方法的完整列表。 2.3. put 方法和自定义 post 如 果 你 想 通 过 put 发送数据,或者想要发送 post , 但 是 想 自 己 创 建 post 数 据 体(body) ,使用 appendPostData: 或者 appendPostDataFromFile:。 ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url]; [request appendPostData:[@"This is my data" dataUsingEncoding:NSUTF8StringEncoding]]; // Default becomes POST when you use appendPostData: / appendPostDataFromFile: / setPostBody: [request setRequestMethod:@"PUT"]; ASIHTTPRequest 使用指南(中文版) www.devdiv.com 翻译整理 DevDiv 翻译:dymx101 11 DevDiv 校对:dymx101 DevDiv 编辑:BeyondVincent 版本 1.0 | 2011 年 9 月 某 日 如果你想发送大量的数据,并且不用 ASIFormDataRequest,参看后面的‘从磁盘以流式 post 数据’小节。 ASIHTTPRequest 使用指南(中文版) www.devdiv.com 翻译整理 DevDiv 翻译:dymx101 12 DevDiv 校对:dymx101 DevDiv 编辑:BeyondVincent 版本 1.0 | 2011 年 9 月 某 日 第 3 章 下载数据 3.1. 将响应数据直接下载为文件 如果你请求的数据相当大,你可以直接将下载内存直接保存为文件。这样,ASIHTTPRequest 不需要一次 在内存中保存整个请求。 ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url]; [request setDownloadDestinationPath:@"/Users/ben/Desktop/my_file.txt"]; 当使用 downloadDestinationPath 下载到文件时,下载过程中,数据将被保存在一个临时文件中。这个文件 路径保存于 temporaryFileDownloadPath。当请求成功完成,下面的事情之一会发生: 如果数据时 gzip 压缩过的,压缩文件将被解压到 downloadDestinationPath,并且临时文件被删除; 如果数据没被压缩,临时文件移动到 downloadDestinationPath,覆盖掉任何之前的文件。 注意:如果响应 body 是空的,文件是不会被创建的。所以如果请求可能返回一个空的 body,你要确定在 尝试操作文件之前,检查它是否存在。 3.2. 处理收到的响应数据 如果你需要处理收到的响应数据,比如你想使用流解析器(streaming parser)来解析仍在下载的响应数据, 就 需 要 在 委 托 中 实 现 request:didReceiveData: 方法。注意当你这么做时, ASIHTTPRequest 不会产生 responseData,也不会将数据写入 downloadDestinationPath -你必须自己搞定保存响应数据的事。 3.3. 读取 HTTP 状态码 ASIHTTPRequest 不会鸟大多数的 http 状态码,重定向和验证的状态码除外。所以,就要靠你检查问题, 比如 404 错误,然后确定你做了恰当的处理。 ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url]; [request startSynchronous]; int statusCode = [request responseStatusCode]; NSString *statusMessage = [request responseStatusMessage]; 3.4. 读取响应头 ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url]; [request startSynchronous]; NSString *poweredBy = [[request responseHeaders] objectForKey:@"X-Powered-By"]; NSString *contentType = [[request responseHeaders] objectForKey:@"Content-Type"]; 3.5. 处理文本编码 ASIHTTPRequest 会尝试从 Content-Type 头得到数据的编码。如果它发现了一个编码类型,他会社子 ASIHTTPRequest 使用指南(中文版) www.devdiv.com 翻译整理 DevDiv 翻译:dymx101 13 DevDiv 校对:dymx101 DevDiv 编辑:BeyondVincent 版本 1.0 | 2011 年 9 月 某 日 responseEncoding 为相应的 NSStringEncoding。如果它没在头部发现编码信息,就会用 defaultResponseEncoding, 这个值默认为 NSISOLatin1StringEncoding。 当你调用[request responseString],ASIHTTPRequest 将尝试用 responseEncoding 作为源编码,从收到的数 据创建一个字符串。 3.6. 处理重定向 当 ASIHTTPRequest 碰到以下 http 状态码时,会自动重定向到一个新的 url,假设 Location 头已经发送: 301 永久移动 302 发现 303 参看其他 当重定向发生,响应数据(responseHeaders / responseCookies / responseData / responseString 等) 的值将反映 从最终位置收到的内容。 在重定向周期中碰到的任何 url 上设置的 Cookie,都倍存储到全局 cookie 仓库,在恰当的时候会由重定向 请求呈现给服务器。 你可以关闭自动重定向,设置 shouldRedirect 属性为 no 即可。 注意:默认情况下,自动重定向总是以 get 方式进行请求(没有 body)。这个行为复合大多数的浏览器,除 了象 301 和 302 这样应该用原有方式重定向的规范。 为了保留 301 和 302 的原有方式(包含请求的 body),需要将 shouldUseRFC2616RedirectBehaviour 设置为 yes,在你开始请求之前。 ASIHTTPRequest 使用指南(中文版) www.devdiv.com 翻译整理 DevDiv 翻译:dymx101 14 DevDiv 校对:dymx101 DevDiv 编辑:BeyondVincent 版本 1.0 | 2011 年 9 月 某 日 第 4 章 跟踪进度 4.1. 介绍 每个 ASIHTTPRequest 都有两个用于跟踪进度的委托- downloadProgressDelegate 用 于 下 载 , uploadProgressDelegate 用于上传。 进度委托可以是 NSProgressIndicators(Mac OS X)或者 UIProgressViews(iPhone)。ASIHTTPRequest 会自动 适应这两者行为上的差异。你也能够使用自定义的类作为进度委托,只要它响应 setProgress:方法。 如果你正执行单个请求,在这个请求上设置一个上传或下载委托。 如果你在队列中执行多个请求,并且想跟踪队列中所有请求的总体进度,可以使用 ASINetworkQueue 并 设置队列的进度委托 如果想同时做上面两件事,也是可行的。 重点注意:如果你正在向需要验证的站点进行上传操作,为了提供有效验证,每当上传失败时,进度会被 重设为之前的值。为此,如果你正同验证 web 服务器通信,建议你仅当 useSessionPersistence 为 yes 时使用上 传进度委托,并确保你在尝试跟踪大量上传数据前,在另一个请求中验证。 当请求 body 小于 128kb 时,目前是不能够跟踪上传进度的。对请求大于 128kb 的请求,进度委托不会收 到第一个 128kb 的 post 数据进度的信息。这是因为 CFNetwork API 的限制造成的。 2009.6.21 日更新:apple 的好家伙非常友好的定位了我的 bug 报告!在 iphone 2.0 sdk 中,貌似这个缓冲尺 寸减小到了 32kb,这让精确的上传进度跟踪更加可靠了。 4.2. 跟踪单个请求的下载进度 在这个例子中,myProgressIndicator 是一个 NSProgressIndicator。 ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url]; [request setDownloadProgressDelegate:myProgressIndicator]; [request startSynchronous]; NSLog(@"Max: %f, Value: %f", [myProgressIndicator maxValue],[myProgressIndicator doubleValue]); 4.3. 跟踪一组请求的下载进度 这个例子中,myProgressIndicator 是一个 UIProgressView,myQueue 是一个 ASINetworkQueue。 - (void)fetchThisURLFiveTimes:(NSURL *)url { [myQueue cancelAllOperations]; [myQueue setDownloadProgressDelegate:myProgressIndicator]; [myQueue setDelegate:self]; [myQueue setRequestDidFinishSelector:@selector(queueComplete:)]; int i; for (i=0; i<5; i++) { ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url]; [myQueue addOperation:request]; } [myQueue go]; } - (void)queueComplete:(ASINetworkQueue *)queue ASIHTTPRequest 使用指南(中文版) www.devdiv.com 翻译整理 DevDiv 翻译:dymx101 15 DevDiv 校对:dymx101 DevDiv 编辑:BeyondVincent 版本 1.0 | 2011 年 9 月 某 日 { NSLog(@"Value: %f", [myProgressIndicator progress]); } 注意对于 ASINetworkQueues,我们必须调用[myQueue go]来启动队列。 4.4. 跟踪单个请求的上传进度 本例中,myProgressIndicator 是一个 UIProgressView。 ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url]; [request setPostValue:@"Ben" forKey:@"first_name"]; [request setPostValue:@"Copsey" forKey:@"last_name"]; [request setUploadProgressDelegate:myProgressIndicator]; [request startSynchronous]; NSLog(@"Value: %f",[myProgressIndicator progress]); 4.5. 跟踪一组请求的上传进度 本例中,myProgressIndicator 是一个 NSProgressUbdicator,myQueue 是一个 ASINetworkQueue。 - (void)uploadSomethingFiveTimes:(NSURL *)url { [myQueue cancelAllOperations]; [myQueue setUploadProgressDelegate:myProgressIndicator]; [myQueue setDelegate:self]; [myQueue setRequestDidFinishSelector:@selector(queueComplete:)]; int i; for (i=0; i<5; i++) { ASIHTTPRequest *request = [ASIFormDataRequest requestWithURL:url]; [request setPostBody:[@"Some data" dataUsingEncoding:NSUTF8StringEncoding]]; [myQueue addOperation:request]; } [myQueue go]; } - (void)queueComplete:(ASINetworkQueue *)queue { NSLog(@"Max: %f, Value: %f", [myProgressIndicator maxValue],[myProgressIndicator doubleValue]); } 4.6. 精确进度 vs 简单进度 ASIHTTPRequest 提供了两种显示进度的途径,简单进度和精确进度。他们由 ASIHTTPRequests 和 ASINetworkQueues 的 showAccurateProgress 来控制。如果你在一个请求上设置 showAccurateProgress,只会影 响这个请求。如果你设置了队列,将影响到队列的全部请求。 ASIHTTPRequest 使用指南(中文版) www.devdiv.com 翻译整理 DevDiv 翻译:dymx101 16 DevDiv 校对:dymx101 DevDiv 编辑:BeyondVincent 版本 1.0 | 2011 年 9 月 某 日 4.6.1. 简单请求 当你使用简单进度,进度仅在请求完成时更新。对于单个进程,你只能得到 0%和 100%完成。对于一个 包括 4 个请求的队列,你能得到 5 次进度更新,0%,25%,50%,75%和 100%,每一次增量表明有一个请 求完成了。 简单进度(showAccurateProgress = NO)是 ASINetworkQueues 的默认值,它很好的适用于包含大量的 轻量级上传/下载请求的队列。 4.6.2. 精确进度 使用精确进度时,进度以收发的字节来更新,所以极适合收发大量数据的请求,它会更好的指示一个耗时 请求收发了多少数据。 使用精确进度会稍稍降低上传操作的性能,因为进度委托(可能是 UIProgressView 或者 NSProgressIndicator)将更为频繁的重绘。 使用精确进度会对使用队列的下载任务影响更大,因为队列在下载前,会先为其中的 get 请求执行 head 请 求,来决定将要下载的数据总体尺寸。强烈推荐你在队列中下载大文件时使用精确进度,但是应该避免队列中 包含大量小型下载时使用它。 精确进度(showAccurateProgress = YES)是 ASIHTTPRequests 执行同步任务时的默认值。 4.7. 自定义进度跟踪 ASIProgressDelegate 协议定义了得到请求的更新进度的委托的所有方法。大多数情况下,为 NSProgressIndicator 或 UIProgressView 设置 uploadProgressDelegate 或 downloadProgressDelegate 就足够了。但 是,如果你想做更复杂的进度跟踪,你的进度委托应该优先于 setProgress: (iOS) 或者 setDoubleValue: / setMaxValue: (Mac)实现下列方法。这些方法允许你得到收发的实际字节数,而不是更简单的方法得到的介于 0 和 1 之间的数字。 downloadProgressDelegates 的方法 request:didReceiveBytes:每当请求下载更多数据时在 downloadProgressDelegate 上调用。注意这有别于一般 会实现的 request:didReceiveData:委托。 request:incrementDownloadSizeBy:下载尺寸改变时被调用,传入的参数是下载尺寸的增量。一般发生在请 求收到响应头并获得了下载的尺寸时。 uploadProgressDelegates 的方法 request:didSendBytes: 每当请求能发送一些数据时在 uploadProgressDelegate 上调用。重点提醒:这个方法 能被小于 0 的数字调用,当一个请求需要删除上传进度时(一般是当它已经上传了数据,但是验证失败或者由 于某种原因需要再次运行时)。 request:incrementUploadSizeBy: 上传尺寸改变时调用。传入的尺寸经常会小于 0,由于请求调整了上传尺 寸,它将 os 内部的缓冲尺寸也计算在内了。 ASIHTTPRequest 使用指南(中文版) www.devdiv.com 翻译整理 DevDiv 翻译:dymx101 17 DevDiv 校对:dymx101 DevDiv 编辑:BeyondVincent 版本 1.0 | 2011 年 9 月 某 日 第 5 章 处理 http 验证 5.1. 介绍 如果你正在连接到需要验证的服务器,你大概想要看看这个流程图 http://allseeing-i.com/ASIHTTPRequest/ASIHTTPRequest-AuthenticationProcess.pdf ,演示了 ASIHTTPRequest 如何找到和应用请求验证。 5.2. 在 url 中指定用户名和密码 NSURL *url = [NSURL URLWithString:@"http://username:password@allseeing-i.com/top_secret/"]; ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url]; 5.3. 设置请求的用户名和密码 NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com/top_secret/"]; ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url]; [request setUsername:@"username"]; [request setPassword:@"password"]; 5.4. 在钥匙串(keychain)中储存证书 如果你打开了 keychainPersistence,任何你提供的有效用户名和密码将被存储到钥匙串中。随后的请求会 重用钥匙串中的用户名和密码,即使你退出再重启应用。 NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com/top_secret/"]; ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url]; [request setUseKeychainPersistence:YES]; [request setUsername:@"username"]; [request setPassword:@"password"]; 如果你使用钥匙串同时希望自己管理它,你应该能在 ASIHTTPRequest.h 中找到有助于此与钥匙串相关的 类方法。 5.5. 在会话中储存 如果 useSessionPersistence 打开了,默认是打开的,ASIHTTPRequest 将证书保存到内存,并可以在后续请 求中重用他们。 NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com/top_secret/"]; ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url]; [request setUsername:@"username"]; [request setPassword:@"password"]; [request setUseSessionPersistence:YES]; //Shouldn't be needed as this is the default //Should reuse our username and password request = [ASIHTTPRequest requestWithURL:url]; 5.6. NTML 验证 要通过使用 ntml 方案的 windows 服务器进行验证,你还需要指定你验证的域(domain)。 ASIHTTPRequest 使用指南(中文版) www.devdiv.com 翻译整理 DevDiv 翻译:dymx101 18 DevDiv 校对:dymx101 DevDiv 编辑:BeyondVincent 版本 1.0 | 2011 年 9 月 某 日 NSURL *url = [NSURL URLWithString:@"http://my.windows.server/top_secret/"]; ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url]; [request setUsername:@"username"]; [request setPassword:@"password"]; [request setDomain:@"my-domain"]; 5.7. 使用委托来提供证书 相对于提前指定验证证书,你可能更愿意在请求不能从会话验证缓存或钥匙串中得到证书时,向它的委托 询问。这可能有助于你希望连到一个服务器,但你不确定它需要哪种类型的验证。 确定你的委托实现了 authenticationNeededForRequest,ASIHTTPRequest 会暂停一个请求,当它等待一个 委托以获得将要使用的证书时。当你有你需要的证书时,只要在请求上设置他们,然后调用 [request retryUsingSuppliedCredentials],如果你想取消,就要调用[request cancelAuthentication],这也会取消请求。 对于 v1.0.8 ,请求的委托一次只会收到一个 authenticationNeededForRequest 或者 proxyAuthenticationNeededForRequest。当委托处理第一个请求时,其他需要验证的请求会暂停执行。如果证书 通过验证,任何当前进程的其他请求都会尝试重用他们,假设他们对 url 有效。如果委托取消了验证,且队列 的 shouldCancelAllRequestsOnFailure 为 yes,所有其他的请求不再尝试查询证书而会取消。 在使用同步请求时,你不能使用代理模式进行验证。 在老版本中这会导致应用挂起,对于 v1.0.8 代理方法不再被调用。 5.8. 使用内置验证对话框(目前仅 ios 可用) 在 v1.0.8 中新增了 ASIAuthenticationDialog 类。它主要用来和验证代理一同工作,但是它可以被用来为验 证 web 服务器询问用户的证书。 为了最好的用户体验,多数连到单个服务的应用应该在其委托中实现 authenticationNeededForRequest:,或 者避免完全的使用委托样式(delegate-style)验证。但是有时为常规验证而使用 ASIHTTPRequest 的标准验证对话 框有些好处: 你不想创建你自己的登录表单 你大概需要从外部来源获得数据,而不太确定它需不需要验证。 为此, 在 请 求 中 设 置 shouldPresentAuthenticationDialog 为 true ,如果你的委托没有实现 authenticationNeededForRequest,用户将看到此对话框。 验证对话框不会在同步请求时出现。 对话框有点模仿了 iphone 上的 safari,并包括: 一条消息指明这个认证是为 web 服务器做的(而不是代理) 你连接到的服务器的主机名或 ip 验证域(authentication realm),如果支持的话 输入用户名和密码的文本框 当连接到一个使用 ntlm 方案的服务器时,对话框也包括一个输入域(domain)的文本框 关于验证是否以明文(plain text)发送的提示(仅在用无 ssl 的基本验证时才被明文发送)。 如果你想改变对话框的外观,子类化 ASIHTTPRequest,重载 showAuthenticationDialog 来显示你自己的自 定义对话框或者子类化 ASIAuthenticationDialog。 ASIHTTPRequest 使用指南(中文版) www.devdiv.com 翻译整理 DevDiv 翻译:dymx101 19 DevDiv 校对:dymx101 DevDiv 编辑:BeyondVincent 版本 1.0 | 2011 年 9 月 某 日 5.9. 在服务器要求之前提供证书 非常重要:在 v1.0.8 中,使用基本验证的请求时,这个特征改变了,你可能需要更新你的代码。 ASIHTTPRequest 可以在首次请求时就为服务器提供证书,而不是等到服务器要求证书。结果是使用验证 时获得更好的性能,因为它避免了额外的请求。 使用基本验证来触发此行为时,你应该手动设置请求的 authenticationScheme: [request setAuthenticationScheme:(NSString *)kCFHTTPAuthenticationSchemeBasic]; 使用其他验证方案时,证书可以在服务器要求之前提供,但只有在另一个请求成功通过此服务器验证之后。 你可能希望禁用此特征,如果: 你的应用可能使用多组证书来同时和同一个服务器对话。 你的应用是安全至上的,使用这个特性本身不太安全,因为在你有机会验证你连接到你希望连接的服务器 之前,证书已经被发送了。 为了禁用此特征,使用以下代码: [request setShouldPresentCredentialsBeforeChallenge:NO]; ASIHTTPRequest 使用指南(中文版) www.devdiv.com 翻译整理 DevDiv 翻译:dymx101 20 DevDiv 校对:dymx101 DevDiv 编辑:BeyondVincent 版本 1.0 | 2011 年 9 月 某 日 第 6 章 Cookies 6.1. 持久化 cookies ASIHTTPRequest 允许你使用全局存储,全局存储为所有 max os 上使用 CFNetwork 或 NSURLRequest API 的 应 用 所 共 享 。 如 果 useCookiePersistence 为 on ( 默 认 如 此 ) , cookies 将 被 保 存 到 共 享 的 NSHTTPCookieStorage 容器中,并自动被其他请求自动重用。如果 cookie 仅 对 特 定 请 求 有 效 , ASIHTTPRequest 提供其他程序创建的 cookie 是没有价值的。 你可以象这样清除在会话中创建的所有 cookie: [ASIHTTPRequest setSessionCookies:nil]; 这里,'会话 cookie'指的一个会话中创建的所有 cookie,而不是程序退出时被删除的无过期时间的 cookie(经常被称为会话 cookie)。 另外,类的方便(convenience)方法 clearSession 将清除所有会话中创建的 cookie,以及任何缓存的验证数据。 6.2. 手工处理 cookie 如果你喜欢,你可以关掉 useCookiePersistence,然后手动管理特定请求的一组 cookie。 //Create a cookie NSDictionary *properties = [[[NSMutableDictionary alloc] init] autorelease]; [properties setValue:[@"Test Value" encodedCookieValue] forKey:NSHTTPCookieValue]; [properties setValue:@"ASIHTTPRequestTestCookie" forKey:NSHTTPCookieName]; [properties setValue:@".allseeing-i.com" forKey:NSHTTPCookieDomain]; [properties setValue:[NSDate dateWithTimeIntervalSinceNow:60*60] forKey:NSHTTPCookieExpires]; [properties setValue:@"/asi-http-request/tests" forKey:NSHTTPCookiePath]; NSHTTPCookie *cookie = [[[NSHTTPCookie alloc] initWithProperties:properties] autorelease]; //This url will return the value of the 'ASIHTTPRequestTestCookie' cookie url = [NSURL URLWithString:@"http://allseeing-i.com/ASIHTTPRequest/tests/read_cookie"]; request = [ASIHTTPRequest requestWithURL:url]; [request setUseCookiePersistence:NO]; [request setRequestCookies:[NSMutableArray arrayWithObject:cookie]]; [request startSynchronous]; //Should be: I have 'Test Value' as the value of 'ASIHTTPRequestTestCookie' NSLog(@"%@",[request responseString]); ASIHTTPRequest 使用指南(中文版) www.devdiv.com 翻译整理 DevDiv 翻译:dymx101 21 DevDiv 校对:dymx101 DevDiv 编辑:BeyondVincent 版本 1.0 | 2011 年 9 月 某 日 第 7 章 处理压缩的响应,以及压缩请求 body 7.1. 使用 gzip 来处理压缩的响应数据 对于 v0.9,ASIHTTPRequest 不会提醒服务器它可以接受 gzip 压缩格式数据。如果你在现有项目中升级 ASIHTTPRequest,参看设置指令地址 http://allseeing-i.com/ASIHTTPRequest/Setup-instructions 了解如何链接到 zlib。 许多 web 服务器可以在发送数据前进行压缩-这样可以加快下载和降低使用带宽,代价是服务器(用以压 缩数据)和客户端(解压数据)增加了额外的 cpu 时间。一般说来,只有某些类型的数据会被压缩 - 许多二进制 格式例如 jpeg,gif,png,swf 和 pdf 已经压缩过他们的数据,所以 gzip 压缩不会用于发送他们到客户端。文本文件 如网页和 xml 文档是 gzip 压缩的完美候选人,因为他们经常包含大量重复信息。 如何设置 apache 使用 mod_deflate 来压缩数据 apatche 2.x 之后带来了 mod_deflate 扩展允许透明的压缩某些类型的数据。要打开他,你需要在 apatche 配 置文件中启用 mode_deflate,并添加 mod_deflate 指令到你的虚拟主机配置中,或者到你的.htaccess 文件中。 在 ASIHTTPRequest 中使用 gzip - (IBAction)grabURL:(id)sender { NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com"]; ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url]; // YES is the default, you can turn off gzip compression by setting this to NO [request setAllowCompressedResponse:YES]; [request startSynchronous]; BOOL *dataWasCompressed = [request isResponseCompressed]; // Was the response gzip compressed? NSData *compressedResponse = [request rawResponseData]; // Compressed data NSData *uncompressedData = [request responseData]; // Uncompressed data NSString *response = [request responseString]; // Uncompressed data as a string } 当 allowCompressedResponse 为真,ASIHTTPRequest 将添加 Accept-Encoding 头到请求中,表明我们可以 接受 gzip 压缩的响应数据。如果响应头包含一个 content-encoding 头指明了数据已被压缩,调用 responseData 或者 responseString 将在返回前解压数据。你可以通过调用 rawResponseData 得到原始压缩数据。 7.2. 联机解压 gzip 响应包 默认的,ASIHTTPRequest 会 一 直 等 到 请 求 完 成 对 gzip 响应包的解压缩。设置 shouldWaitToInflateCompressedResponses 属性为 no,你可以告诉 ASIHTTPRequest 在收到数据同时进行解压。 有时候,这会提升一点速度,因为当一个请求等待更多响应时,数据可以同时被处理。 这个特性对于需要使用流解析器(streaming parser)如 xml 或 json 解析器时尤其有用,打开这个选项,你可 以直接给你的解析器输送解压过的数据,他们来自你委托实现的 request:didReceiveData: 方法。 注意当 shouldWaitToInflateCompressedResponses 为 no 时,原始( 压缩过的) 数据将被丢弃,参看 ASIHTTPRequest.h 的注释获得更多信息。 ASIHTTPRequest 使用指南(中文版) www.devdiv.com 翻译整理 DevDiv 翻译:dymx101 22 DevDiv 校对:dymx101 DevDiv 编辑:BeyondVincent 版本 1.0 | 2011 年 9 月 某 日 7.3. 使用 gzip 来压缩请求 body v1.0.3 新增了请求 body 的 gzip 压缩。使用这个特性,你的应用可以压缩 post/put 操作的内容,只要设置 shouldCompressRequestBody 为 yes 即可。shouldCompressRequestBody 默认为 no。 当你配置了 SetInputFilter DEFLATE 后,apatche 的 mod_deflate 可以自动的解压 gzip 请求体。这个方法为 cgi 内容工作,但是如果你使用 apatche 模块构建成了一个 RESOURCE 过滤器(如 mod PHP)则不能工作,这时 你需要自己搞定数据解压。 注意:ASIHTTPRequest 不能检查到服务器是否接受 gzip 请求体。只有当你确定服务器能搞定 gzip body 时使用这项特性。 避免对压缩格式文件如 jpeg/png/gif/pdf/swf 使用 gzip,你会发现 gzip 版本会比原始文件大。 ASIHTTPRequest 使用指南(中文版) www.devdiv.com 翻译整理 DevDiv 翻译:dymx101 23 DevDiv 校对:dymx101 DevDiv 编辑:BeyondVincent 版本 1.0 | 2011 年 9 月 某 日 第 8 章 恢复被打断的下载 8.1. 如何恢复下载 自 v0.94 开始,ASIHTTPRequest 能够恢复不完整的下载 - (IBAction)resumeInterruptedDownload:(id)sender { NSURL *url = [NSURL URLWithString: @"http://allseeing-i.com/ASIHTTPRequest/Tests/the_great_american_novel.txt"]; ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url]; NSString *downloadPath = @"/Users/ben/Desktop/my_work_in_progress.txt"; // The full file will be moved here if and when the request completes successfully [request setDownloadDestinationPath:downloadPath]; // This file has part of the download in it already [request setTemporaryFileDownloadPath:@"/Users/ben/Desktop/my_work_in_progress.txt.download"]; [request setAllowResumeForFileDownloads:YES]; [request startSynchronous]; //The whole file should be here now. NSString *theContent = [NSString stringWithContentsOfFile:downloadPath]; } 这只在下载数据到文件时有用,你必须设置 allowResumeForFileDownloads 为 yes,为了: 任何你将来可能想恢复的下载(或者 ASIHTTPRequest 会在取消或释放时删除的临时下载) 任何你想恢复的下载 而且,你必须设置一个临时下载路径(setTemporaryFileDownloadPath),用不完整数据的路径,新数据将被 追加到这个文件,当下载成功,这个文件会被移到 downloadDestinationPath。 ASIHTTPRequest 不会检查 accept-range 头(因为额外 head 请求的负担),所以仅在确定服务器能够支持 不完整下载时才使用此特征。 ASIHTTPRequest 使用指南(中文版) www.devdiv.com 翻译整理 DevDiv 翻译:dymx101 24 DevDiv 校对:dymx101 DevDiv 编辑:BeyondVincent 版本 1.0 | 2011 年 9 月 某 日 第 9 章 直接从磁盘流式请求 body 9.1. 介绍 自 v0.96 开始,ASIHTTPRequest 能够使用磁盘文件作为请求 body。这意味着将请求 body 保持在内存不再 必要,这样一来,大型的 post/put 操作的将极大的减少内存使用量。 你可以以几种方法来使用这一特征: 9.2. ASIFormDataRequests NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com/ignore"]; ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url]; [request setPostValue:@"foo" forKey:@"post_var"]; [request setFile:@"/Users/ben/Desktop/bigfile.txt" forKey:@"file"]; [request startSynchronous]; ASIFormDataRequests 在你使用 setFile:forKey:,自动使用这一特性。请求将创建临时文件,包含完整的请 求 body。文件一次写入一些 body 的相关部分。请求被 CFReadStreamCreateForStreamedHTTPRequest 创建,使 用此文件上的读取流作为来源。 9.3. 常规的 ASIHTTPRequest 如果你知道你的请求将会很大,可以在请求上打开磁盘流(streaming from disk): [request setShouldStreamPostDataFromDisk:YES]; 在下面的例子中,我们每次添加一个 NSData 对象。有两个方法做这个事-从内存添加数据 (appendPostData:),或者使用 appendPostDataFromFile 从文件添加内容。 NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com/ignore"]; ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url]; [request setShouldStreamPostDataFromDisk:YES]; [request appendPostData:myBigNSData]; [request appendPostDataFromFile:@"/Users/ben/Desktop/bigfile.txt"]; [request startSynchronous]; 在本例中,我们想要直接 put 一个大文件。我们自己设置 setPostBodyFilePath,ASIHTTPRequest 将使用这 个文件作为 post body。 NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com/ignore"]; ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url]; [request setRequestMethod:@"PUT"]; [request setPostBodyFilePath:@"/Users/ben/Desktop/another-big-one.txt"]; [request setShouldStreamPostDataFromDisk:YES]; [request startSynchronous]; 非常重要:你不应该在上面任何方法的同一个请求中使用 setPostBody -他们是互斥的,setPostBody 只能 用于你自己构建请求 body,并计划将请求 body 保留到内存的情型。 ASIHTTPRequest 使用指南(中文版) www.devdiv.com 翻译整理 DevDiv 翻译:dymx101 25 DevDiv 校对:dymx101 DevDiv 编辑:BeyondVincent 版本 1.0 | 2011 年 9 月 某 日 第 10 章 使用下载缓存 10.1. 介绍 ASIDownloadCache 以及 ASICacheDelegate 的 API 在 v1.8 中已经改变,如果从 v1.7 升级的话,你需要更 新你的代码。 特别是,缓存策略的可用选项是不同的,并且你现在可以将多个缓存策略合并到单个请求中。 ASIHTTPRequest 可以自动保存下载数据到一个缓存,以便以后使用。许多情况下这会很有帮助: 你想要访问数据,在没有因特网连接不能重新下载时; 你想下载些东西,仅在你上次下载后它有了变化时; 你用的内容永不改变,所以你只想下载它一次; 在之前的 ASIHTTPRequest 版本中,处理以上情况意味着你自己手动保存这些数据。使用一个下载缓存可 以在一些情况下减少你自己编写本地存储机制的需求。 ASIDownloadCache 是一个简单的 url 缓存,可以被用于缓存 get 请求的响应。为了符合响应缓存的条件, 请求必须成功(没有错误),服务器必须返回一个 200 ok 的 http 响应码,或者从 v1.8.1 开始,支持 301,302,303,307 重定向的状态码。 开启响应缓存很简单: [ASIHTTPRequest setDefaultCache:[ASIDownloadCache sharedCache]]; 开启之后,所有的请求会自动使用缓存。如果你喜欢,你可以为独立的请求设置共享缓存: ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url]; [request setDownloadCache:[ASIDownloadCache sharedCache]]; 缓存不限于单个,你可以创建任意多个缓存。当你自己创建缓存时,必须设置缓存的存储路径-这应该是 一个可写的文件夹: ASIDownloadCache *cache = [[[ASIDownloadCache alloc] init] autorelease]; [cache setStoragePath:@"/Users/ben/Documents/Cached-Downloads"]; // Don't forget - you are responsible for retaining your cache! [self setMyCache:cache]; ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url]; [request setDownloadCache:[self myCache]]; 10.2. 关于缓存策略 缓存策略是在信息存储于缓存中时你主要的控制方法,以及何时优先使用缓存的数据,而不是重新下载数 据。 独立请求的缓存策略可以使用它的 cachePolicy 属性。缓存策略使用位掩码(bitmask)定义,所以你可以组 合多个选项来创建想要的策略: // Always ask the server if there is new content available, // If the request fails, use data from the cache even if it should have expired. [request setCachePolicy:ASIAskServerIfModifiedCachePolicy|ASIFallbackToCacheIfLoadFailsCachePolicy]; 你可以使用下列选项来定义一个请求的缓存策略: ASIUseDefaultCachePolicy ASIHTTPRequest 使用指南(中文版) www.devdiv.com 翻译整理 DevDiv 翻译:dymx101 26 DevDiv 校对:dymx101 DevDiv 编辑:BeyondVincent 版本 1.0 | 2011 年 9 月 某 日 默认缓存策略,当你对请求应用此策略时,它会使用缓存的 defaultCachePolicy,ASIDownloadCache 的默 认缓存策略是 ASIAskServerIfModifiedWhenStaleCachePolicy,你不应该将此策略和其他策略组合使用。 ASIDoNotReadFromCacheCachePolicy 请求不会从缓存读取数据 ASIDoNotWriteToCacheCachePolicy 请求不会保存到缓存 ASIAskServerIfModifiedWhenStaleCachePolicy 这是 ASIDownloadCaches 的默认缓存策略。使用了它,请求会首先查看缓存中是否有可用的缓存响应数 据。如果没有,请求会照常进行。 如果有没有过期的缓存数据,请求会使用它而不去访问服务器。如果缓存数据过期了,请求将执行一个有 条件的 get 去获取是否有可用的升级版本。如果服务器表示缓存的数据就是最新的,那么缓存的数据将被使用, 新的数据不会被下载。这时,缓存的过期时间(expiry date)将根据服务器新的过期时间而被更新。如果服务器提 供了更新内容,则将被下载,新的数据和过期时间将被写入缓存。 ASIAskServerIfModifiedCachePolicy 这个策略和 ASIAskServerIfModifiedWhenStaleCachePolicy 相同,只是请求每次都会询问服务器是否有新 的数据 ASIOnlyLoadIfNotCachedCachePolicy 只要存在缓存数据,总是会被使用,即使它已经过期。 ASIDontLoadCachePolicy 请求仅在响应已经被缓存时成功。如果请求没有任何响应被缓存,请求会终止,并且也不会为此请求设置 错误。 ASIFallbackToCacheIfLoadFailsCachePolicy 如果请求失败,将会退回到缓存数据。如果失败后使用了缓存的数据,请求将会成功而不报错。你一般会 将它和其他策略混合使用,因为此策略仅在发生问题时用于指定行为。 当你为缓存设置了 defaultCachePolicy 属性,所有的请求将会使用这个缓存策略,除非他们自己设置了自 定义的策略。 10.3. 关于存储策略 存储策略允许你定义特定响应的缓存将被保存多久,ASIHTTPRequest 目前支持两种存储策略: ASICacheForSessionDurationCacheStoragePolicy 是默认值。响应仅在会话期间被保存,并将在缓存首次使 用后被删除,或者当调用[ASIHTTPRequest clearSession] 时被删除。 使用 ASICachePermanentlyCacheStoragePolicy,缓存数据将被永久保存,要用这个存储策略,可将它设置 到一个请求上: ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url]; [request setCacheStoragePolicy:ASICachePermanentlyCacheStoragePolicy]; 要手动清除缓存,调用 clearCachedResponsesForStoragePolicy,传入你希望清除的缓存数据的存储类型: [[ASIDownloadCache sharedCache] clearCachedResponsesForStoragePolicy:ASICachePermanentlyCacheStoragePolicy]; 10.4. 其他缓存特性 当你关掉 shouldRespectCacheControlHeaders, 响应数据将被保存,即使服务器明确要求不要缓存他们 ASIHTTPRequest 使用指南(中文版) www.devdiv.com 翻译整理 DevDiv 翻译:dymx101 27 DevDiv 校对:dymx101 DevDiv 编辑:BeyondVincent 版本 1.0 | 2011 年 9 月 某 日 // (eg with a cache-control or pragma: no-cache header) [[ASIDownloadCache sharedCache] setShouldRespectCacheControlHeaders:NO]; 为 请 求 设 置 secondsToCache ,覆盖了由服务器设置的任何过期时间,一直保存响应数据直到 secondsToCache 秒到期。 ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url]; [request setSecondsToCache:60*60*24*30]; // Cache for 30 days 在请求运行后,didUseCachedResponse 将在响应由缓存返回时,返回 yes [request didUseCachedResponse]; 询问缓存请求数据的保存路径,这是使用下载缓存最高效的方式,因为数据不必在请求完成后被拷贝到缓 存 [request setDownloadDestinationPath: [[ASIDownloadCache sharedCache] pathToStoreCachedResponseDataForRequest:request]]; 10.5. 写你自己的缓存 如果你已经有一个下载缓存,并想将它接入到 ASIHTTPRequest,或者你想要写自己的缓存,可以让你的 缓存实现 ASICacheDelegate 协议。 ASIHTTPRequest 使用指南(中文版) www.devdiv.com 翻译整理 DevDiv 翻译:dymx101 28 DevDiv 校对:dymx101 DevDiv 编辑:BeyondVincent 版本 1.0 | 2011 年 9 月 某 日 第 11 章 节约带宽 11.1. 如何使用宽带限制 从 v1.0.7 开始,ASIHTTPRequest 能够限制所有请求使用的带宽,防止它超过一个用户定义的上限。这可 以帮助收发大量数据的 iphone 应用通过 app store 的审核程序。 限流工作使用一个全局限制(以字节为单位),来限定每秒能够收发的数据总量。所有的请求共享这个限制。 当他们收发数据时,ASIHTTPRequest 追踪上一秒内有多少数据被收发。如果某个请求超过了限制,任何其他 的执行单位也都必须等待本次测量时段结束。 在 ios 上,你可以让 ASIHTTPRequest 自动打开限流,当你使用一个 wwan(gprs/edge/3g)连接时,而当切换 到 wifi 时,会自动关闭他。 当使用 wwan 激活时将限制带宽到为移动应用预定义的默认值,wifi 请求不受影响,此方法仅限于 ios // Will limit bandwidth to the predefined default for mobile applications when WWAN is active. // Wi-Fi requests are not affected // This method is only available on iOS [ASIHTTPRequest setShouldThrottleBandwidthForWWAN:YES]; 当 wwan 激活后,限制带宽为用户定义的值,仅限 ios // Will throttle bandwidth based on a user-defined limit when when WWAN (not Wi-Fi) is active // This method is only available on iOS [ASIHTTPRequest throttleBandwidthForWWANUsingLimit:14800]; 限制所有请求,不管是不是 wifi,都会限制到预定义的值--小心使用 // Will prevent requests from using more than the predefined limit for mobile applications. // Will limit ALL requests, regardless of whether Wi-Fi is in use or not - USE WITH CAUTION [ASIHTTPRequest setMaxBandwidthPerSecond:ASIWWANBandwidthThrottleAmount]; 记录每秒多少字节的数据被收发(从前 5 秒取平均值) // Log how many bytes have been received or sent per second (average from the last 5 seconds) NSLog(@"%qi",[ASIHTTPRequest averageBandwidthUsedPerSecond]); 非常重要:启用带宽限制之前先读读这个: 带宽限制应被视为一个实验性特征,使用时自行承担风险 不要将带宽限制过底,最好不要低于 ASIWWANBandwidthThrottleAmount 你的应用实际使用的带宽将总是稍稍大于你设置的值,因为带宽测量不包括 http 头使用的带宽 ASIWWANBandwidthThrottleAmount 不是官方的值,据我所知,官方没有发布带宽限制值 你不应该在你的应用并没有大量数据传输时打开带宽限制,仅在有大量数据上传或下载的请求执行时启用 它,其他时间请关闭。 ASIHTTPRequest 使用指南(中文版) www.devdiv.com 翻译整理 DevDiv 翻译:dymx101 29 DevDiv 校对:dymx101 DevDiv 编辑:BeyondVincent 版本 1.0 | 2011 年 9 月 某 日 第 12 章 客户端证书支持 12.1. 如何使用客户端证书 如果你的服务器需要使用客户端证书,v1.8 以后可以通过请求来发送他们。 // Will send the certificate attached to the identity (identity is a SecIdentityRef) [request setClientCertificateIdentity:identity]; // Add an additional certificate (where cert is a SecCertificateRef) [request setClientCertificates:[NSArray arrayWithObject:(id)cert]]; 在 iphone/ipad app 的 ClientCertificateTests.m 中有一个帮助函数,可以从 pkcs12 数 据 创 建 一 个 SecIdentityRef(此函数仅在 ios 中有用)。 ASIHTTPRequest 使用指南(中文版) www.devdiv.com 翻译整理 DevDiv 翻译:dymx101 30 DevDiv 校对:dymx101 DevDiv 编辑:BeyondVincent 版本 1.0 | 2011 年 9 月 某 日 第 13 章 同代理一起工作 13.1. 介绍 ASIHTTPRequest 可以检测到系统代理并且自动将他们应用到请求。从 v1.0.6 开始,他也支持 pac 文件代 理配置,以及验证代理。 默认的,ASIHTTPRequest 将尝试自动检测代理设置,但是,你可能希望能够手动设置代理: // Configure a proxy server manually NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com/ignore"]; ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url]; [request setProxyHost:@"192.168.0.1"]; [request setProxyPort:3128]; // Alternatively, you can use a manually-specified Proxy Auto Config file (PAC) // (It's probably best if you use a local file) [request setPACurl:[NSURL URLWithString:@"file:///Users/ben/Desktop/test.pac"]]; 13.2. 验证代理 在 mac os 上,ASIHTTPRequest 可以自动检测用于验证代理的证书,如果他们在系统参数中指定了的话。 在 ios 上,则不能自动检测,所以你要么手动设置他们,使用委托来询问控制器/相应证书的用户,要么让 ASIAuthenticationDialog 询问用户。一旦有效的代理证书被接受,他们将被保存到钥匙串中 ( 当 useKeychainPersistence 被打开)并自动被重用。 13.3. 手动指定代理的证书 NSURL *url = [NSURL URLWithString:@"http://allseeing-i.com/ignore"]; ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url]; [request setProxyHost:@"192.168.0.1"]; [request setProxyPort:3128]; // Set a username and password for authenticating proxies [request setProxyUsername:@"bencopsey"]; [request setProxyPassword:@"password"]; // For NTLM proxies, you can also set the domain (NTLM proxies are untested!) [request setProxyDomain:@"la.la.land"]; 13.4. 使用委托来询问代理证书 这和使用委托提供常规验证证书的方式一样,除了委托必须响应 proxyAuthenticationNeededForRequest (以前的名字是 proxyAuthorizationNeededForRequest)。 13.5. 使用内置验证对话框(目前仅 ios) v1.0.8 之后新增了 ASIAuthenticationDialog 类。这个类可被用于询问用户 web 服务器或代理的验证证书。 ASIHTTPRequest 使用指南(中文版) www.devdiv.com 翻译整理 DevDiv 翻译:dymx101 31 DevDiv 校对:dymx101 DevDiv 编辑:BeyondVincent 版本 1.0 | 2011 年 9 月 某 日 如果你的委托不能响应 proxyAuthenticationNeededForRequest,默认的,ASIHTTPRequest 将显示一个提示 用户提供证书的对话框。它默认为代理服务器显示,这样所有使用 ASIHTTPRequest 的应用可以同验证代理工 作,而不需要任何开发者端额外的努力。 同步请求时,代理验证对话框不会显示。 如果你不喜欢用代理验证对话框,要么你在你的代理中实现 proxyAuthenticationNeededForRequest,或者 将 shouldPresentProxyAuthenticationDialog 设置为 false(那样你的应用将不能连接到验证代理)。如果你想改 变它的外观,子类化 ASIHTTPRequest 并覆盖 showProxyAuthenticationDialog 来显示你的自定义对话框,或者 子类化 ASIAuthenticationDialog。 ASIHTTPRequest 使用指南(中文版) www.devdiv.com 翻译整理 DevDiv 翻译:dymx101 32 DevDiv 校对:dymx101 DevDiv 编辑:BeyondVincent 版本 1.0 | 2011 年 9 月 某 日 第 14 章 其他特性 14.1. 自定义用户代理 设置你的应用将使用的用户代理: [ASIHTTPRequest setDefaultUserAgentString:@"MyApp 1.0"] 如果你不设置用户代理,ASIHTTPRequest 会为你创建一个,例如(对于 mac os 程序): My Application 1.0 (Macintosh; Mac OS X 10.5.7; en_GB) 你也可以为每个请求设置用户代理: [request setUserAgent:@"MyApp 1.0"] 14.2. 在 ios 中程序进入后台时继续请求 // iOS 4+ only [request setShouldContinueWhenAppEntersBackground:YES]; 14.3. 监视网络活动 // Log the average bandwidth used (in bytes) per second over the last 5 seconds NSLog(@"%llu",[ASIHTTPRequest averageBandwidthUsedPerSecond]); if ([ASIHTTPRequest isNetworkInUse]) { // ASIHTTPRequest has requests in progress that are using the network } 14.4. 禁用自动更新网络活动指示器(仅 ios) 默认的,ASIHTTPRequest 会显示网络活动指示器(在状态条上),当你的请求使用网络时。如果你想要自 己管理这个,你可以禁用这些更新: [ASIHTTPRequest setShouldUpdateNetworkActivityIndicator:NO]; 14.5. 当请求超时自动重试 请求超时,最多重试 2 次: [request setNumberOfTimesToRetryOnTimeout:2]; 14.6. 配置持续连接(persistent connection) 默认的,ASIHTTPRequest 将尝试保持到服务器的连接,这样他们可以被连到相同服务器的请求重用(这一 般导致速度显著提升,特别是你有许多小的请求时)。 ASIHTTPRequest 使用指南(中文版) www.devdiv.com 翻译整理 DevDiv 翻译:dymx101 33 DevDiv 校对:dymx101 DevDiv 编辑:BeyondVincent 版本 1.0 | 2011 年 9 月 某 日 当连接到 http1.1 服务器时,持续连接将自动启用,或者当服务器发回一个 keep-alive 头时。当服务器明确 的发回一个 Connection: close 头时,持续连接将被关闭。另外,ASIHTTPRequest 对于包含 body 的请求(如 post/put),将不会使用持续连接。你可以强制这些请求使用持续连接,手动设置请求方法,然后将持续连接 重新打开: [request setRequestMethod:@"PUT"]; [request setShouldAttemptPersistentConnection:YES]; 许多服务器不在响应头中提供连接保持多久的信息,所以可能在请求完成后的任何时间关闭连接。如果服 务器不发送任何此类信息,ASIHTTPRequest 将在请求完成后 60 秒内保持连接。有赖于你的服务器配置,这个 时间可能过长或过短。 如果这个超时过长,服务器将在下一个请求有机会用它前踢掉你,如果 ASIHTTPRequest 碰到关闭连接的 错误,它将在一个新连接上重试这个请求。 如果这个超时过短,服务器可能很乐意保持这个连接更久,但是 ASIHTTPRequest 将不必要的重开一个新 连接,这会招致效率上的惩罚。 // Set the amount of time to hang on to a persistent connection before it should expire to 2 minutes [request setPersistentConnectionTimeoutSeconds:120]; // Disable persistent connections entirely [request setShouldAttemptPersistentConnection:NO]; 14.7. 强制使用 http 1.0 [request setUseHTTPVersionOne:YES]; 14.8. 禁用安全证书验证 你可能希望使用这个测试你有一个自签名的安全证书。我推荐从一个可信的证书机构购买证书,并且只为 产品程序打开证书验证。 [request setValidatesSecureCertificate:NO]; ASIHTTPRequest 使用指南(中文版) www.devdiv.com 翻译整理 DevDiv 翻译:dymx101 34 DevDiv 校对:dymx101 DevDiv 编辑:BeyondVincent 版本 1.0 | 2011 年 9 月 某 日 第 15 章 调试选项 15.1. ASIHTTPRequest 调试标志信息 ASIHTTPRequest 提供了一些有助于调试请求行为的标志。这些标志可以在 ASITHHPRequestConfig.h 中找 到。 当你打开这些标志后,请求会把他们干的事打印到控制台。 DEBUG_REQUEST_STATUS 打印总体请求的生命周期信息 -- 开始,结束上传,结束下载等等。 DEBUG_THROTTLING 打印(粗略的)有多少带宽被使用的信息,如果请求被限流,还包括这如何发生的信息。同 DEBUG_REQUEST_STATUS 联合使用,可能对调试超时有帮助,因为你可以看到在哪一点请求停止了收发数 据。 DEBUG_PERSISTENT_CONNECTIONS 打印请求如何重用持续连接的信息,如果你看到输出下面的信息: Request attempted to use connection #1, but it has been closed - will retry with a new connection „这表示你设置到 persistentConnectionTimeoutSeconds 的值可能过高,参看“配置持续连接”小节获得更 多信息。 DEBUG_HTTP_AUTHENTICATION 从 v1.8.1 后添加,这会打印出关于请求如何处理 http 验证(基本/摘要/ntml)的信息。 DEBUG_FORM_DATA_REQUEST 打印 ASIFormDataRequest 将发送的请求 body 的概要。仅在使用 ASIFormDataRequest 有用。 (全文完) ====================================================== © Ben Copsey, All-Seeing Interactive 2008-2011. ASIHTTPRequest 使用指南(中文版) www.devdiv.com 翻译整理 DevDiv 翻译:dymx101 35 DevDiv 校对:dymx101 DevDiv 编辑:BeyondVincent 版本 1.0 | 2011 年 9 月 某 日 点击这里访问:DevDiv.com 移动开发论坛
还剩34页未读

继续阅读

下载pdf到电脑,查找使用更方便

pdf的实际排版效果,会与网站的显示效果略有不同!!

需要 10 金币 [ 分享pdf获得金币 ] 1 人已下载

下载pdf

pdf贡献者

q523061314

贡献于2013-04-22

下载需要 10 金币 [金币充值 ]
亲,您也可以通过 分享原创pdf 来获得金币奖励!
下载pdf