ASIHTTPRequest-直接读取磁盘数据流的请求体 ASIHTTPRequest-数据压缩
2013-01-07 10:37
591 查看
从0.96版本开始,ASIHTTPRequest可以使用磁盘上的数据来作为请求体。这意味着不需要将文件完全读入内存中,这就避免的当使用大文件时的严重内存消耗。
使用这个特性的方法有好几种:
当使用setFile:forKey:时,ASIFormDataRequests 自动使用这个特性。request将会创建一个包含整个post体的临时文件。文件会一点一点写入post体。这样的request是由 CFReadStreamCreateForStreamedHTTPRequest创建的,它使用文件读取流来作为资源。
如果你明白自己的request体会很大,那么为这个request设置流式读取模式。
下面的例子中,我们将一个NSData对象添加到post体。这有两个方法:从内存中添加(appendPostData:),或者从文件中添加(appendPostDataFromFile:);
这个例子中,我们想直接PUT一个大文件。我们得自己设置setPostBodyFilePath ,ASIHTTPRequest将使用这个文件来作为post体。
使用这个特性的方法有好几种:
ASIFormDataRequests
1 2 3 4 5 | NSURL *url = [ NSURL URLWithString : @ "http://www.dreamingwish.com/" ]; ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL :url]; [request setPostValue : @ "foo" forKey : @ "post_var" ]; [request setFile : @ "/Users/ben/Desktop/bigfile.txt" forKey : @ "file" ]; [request startSynchronous ]; |
普通ASIHTTPRequest
如果你明白自己的request体会很大,那么为这个request设置流式读取模式。1 | [request setShouldStreamPostDataFromDisk : YES ]; |
1 2 3 4 5 6 | NSURL *url = [ NSURL URLWithString : @ "http://www.dreamingwish.com/" ]; ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL :url]; [request setShouldStreamPostDataFromDisk : YES ]; [request appendPostData :myBigNSData]; [request appendPostDataFromFile : @ "/Users/ben/Desktop/bigfile.txt" ]; [request startSynchronous ]; |
1 2 3 4 5 6 | NSURL *url = [ NSURL URLWithString : @ "http://www.dreamingwish.com" ]; ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL :url]; [request setRequestMethod : @ "PUT" ]; [request setPostBodyFilePath : @ "/Users/ben/Desktop/another-big-one.txt" ]; [request setShouldStreamPostDataFromDisk : YES ]; [request startSynchronous ]; IMPORTANT:切勿对使用上述函数的request使用setPostBody——他们是互斥的。只有在你要自己建立request的请求体,并且还准备在内存中保持这个请求体时,才应该使用setPostBody。 从0.9版本开始,ASIHTTPRequest会提示服务器它可以接收gzip压缩过的数据。 |
1 2 3 4 5 6 7 8 9 10 11 12 | - ( IBAction )grabURL:( id )sender { NSURL *url = [ NSURL URLWithString : @ "http://www.dreamingwish.com" ]; ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL :url]; // 默认为YES, 你可以设定它为NO来禁用gzip压缩 [request setAllowCompressedResponse : YES ]; [request startSynchronous ]; BOOL *dataWasCompressed = [request isResponseCompressed ]; // 响应是否被gzip压缩过? NSData *compressedResponse = [request rawResponseData ]; // 压缩的数据 NSData *uncompressedData = [request responseData ]; // 解压缩后的数据 NSString *response = [request responseString ]; // 解压缩后的字符串 } |
相应数据的实时解压缩
默认情况下,ASIHTTPRequest会等到request完成时才解压缩返回的数据。若设置request的shouldWaitToInflateCompressedResponses 属性为NO,ASIHTTPRequest将会对收到的数据进行实时解压缩。 在某些情况下,这会稍稍提升速度,因为数据可以在reqeust等待网络数据时进行处理。如果你需要对响应数据流进行流处理(例如XML和JSON解析),这个特性会很有用。如果启用了这个选项,你可以通过实现代理函数request:didReceiveData:来将返回的网络数据一点一点喂给解析器。
注意,如果shouldWaitToInflateCompressedResponses 被设置为NO,那么原始(未解压)的数据会被抛弃。具体情况请查阅ASIHTTPRequest.h的代码注释。
使用gzip压缩request数据
1.0.3版本的新特性就是gzip压缩request数据。使用这个特性,你可以通过设置shouldCompressRequestBody 为YES来使你的程序压缩POST/PUT的内容,默认值为NO。apache的mod_deflate可以自动解压缩gzip压缩的请求体(通过合适的设置)。这个方法适用于CGI内容,但不适用于内容过滤器式的模块(例如mod PHP),这种情况下,你就必须自己解压缩数据。
ASIHTTPRequest 无法检测一个服务器是否能接收压缩过的请求体。当你确定服务器可以解压缩gzip包时,再使用这个特性。
请避免对已经压缩过的格式(例如jpeg/png/gif/pdf/swf)进行压缩,你会发现压缩后的数据比原数据更大。(梦维:因为压缩包都有头信息)
ASIHTTPRequest-身份验证
你可以查阅ASIHTTPRequest授权流程图来了解ASIHTTPRequest如何找到授权凭据,并将授权凭据应用到request上。
为URL指定要使用的用户名和密码
1 2 | NSURL *url = [ NSURL URLWithString : @ "http://www.dreamingwish.com/" ]; ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL :url]; |
为request指定要使用的用户名和密码
1 2 3 4 | NSURL *url = [ NSURL URLWithString : @ "http://www.dreamingwish.com/" ]; ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL :url]; [request setUsername : @ "username" ]; [request setPassword : @ "password" ]; |
将凭据存储到keychain
如果打开了keychainPersistence,所有提供的可用的用户名和密码将被存储到keychain中,以后的request将会重用这些用户名密码,即使你关闭程序后重新打开也不影响。1 2 3 4 5 | NSURL *url = [ NSURL URLWithString : @ "http://www.dreamingwish.com/" ]; ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL :url]; [request setUseKeychainPersistence : YES ]; [request setUsername : @ "username" ]; [request setPassword : @ "password" ]; |
将凭据存储到session中
如果打开了useSessionPersistence(默认即是如此),ASIHTTPRequest会把凭据存储到内存中,后来的request将会重用这些凭据。1 2 3 4 5 6 7 8 | NSURL *url = [ NSURL URLWithString : @ "http://www.dreamingwish.com/" ]; ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL :url]; [request setUsername : @ "username" ]; [request setPassword : @ "password" ]; [request setUseSessionPersistence : YES ]; //这一项是默认的,所以并不必要 //将会重用我们的 username 和 password request = [ASIHTTPRequest requestWithURL :url]; |
NTLM授权
要使用NTLM授权的Windows服务器,你还需要指定你要进行授权域。1 2 3 4 5 | NSURL *url = [ NSURL URLWithString : @ "http://www.dreamingwish.com/" ]; ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL :url]; [request setUsername : @ "username" ]; [request setPassword : @ "password" ]; [request setDomain : @ "my-domain" ]; |
使用代理来提供凭据
你不一定非要提前指定授权凭据,你还可以让每个request在无法从session或keychain中找到凭据时向它们的代理请求凭据。如果你要连接到一个你并不清楚授权类型的服务器时,这是很有用的。你的delegate必须实现authenticationNeededForRequest:方法,当request等待凭据 时,ASIHTTPRequest将会暂停这个request。如果你持有你需要的凭据,那么先为request设定凭据,然后调用[request retryUsingSuppliedCredentials]即可。如果你想取消授权,调用[request cancelAuthentication],此时,这个request也会被取消。
从1.0.8版开始,一次只能有一个request的delegate收到authenticationNeededForRequest: 或者 proxyAuthenticationNeededForRequest:。当delegate处理第一个request时,其他需要授权的 request将会被暂停。如果提供了一个凭据,当前进程中所有其他的request将会假定这个凭据对这个URL有效,并尝试重用这个凭据。如果 delegate取消了授权,并且队列的shouldCancelAllRequestsOnFailure值为YES,所有其他的request都将被
取消(它们也不会尝试请求凭据)。
当进行同步请求时,你不可以使用代理模式来授权。
在较老的版本中,这么做会导致程序假死,从1.0.8开始,即使你这么做了,代理函数也不会被调用。
使用内建的授权对话框(目前只对iOS有效)
这个特性归功于1.0.8版本的新类ASIAuthenticationDialog 。这个特性主要是用于授权代理(后面会介绍到),但是它也可以用来向用户取得授权凭据。
为了更好的用户体验,大多数(连接单一服务的)app必须为request的delegate实现authenticationNeededForRequest:方法,或者避免同时使用代理式授权。
most apps that connect to a single service should implement authenticationNeededForRequest: in their request delegates, or avoid the use of delegation-style authentication altogether.
但是,会有一些情况下,为普通的授权使用ASIHTTPRequest的标准授权对话框更好:
你不想创建你自己的登录表单
你可能需要从外部资源获取数据,但是你不清楚你需不需要进行授权
对于这些情况,为request设置shouldPresentAuthenticationDialog为YES,此时,如果你的代理没有实现
authenticationNeededForRequest:方法,那么用户将会看到这个对话框。
一次同时只有一个对话框可以显示出来,所以当一个对话框显示时,所有其他需要授权的request将会暂停。如果提供了一个凭据,当前进程中所有其 他的request将会假定这个凭据对这个URL有效,并尝试重用这个凭据。如果delegate取消了授权,并且队列的 shouldCancelAllRequestsOnFailure值为YES,所有其他的request都将被取消(它们也不会尝试请求凭据)。
对于同步请求的request,授权对话框不会显示出来。
这个对话框部分模仿了iPhone上Safari使用的授权对话框,它包含以下内容:
一段信息来说明这些凭据是用于websever(而非一个proxy)
你将要连接到服务器的主机名或者IP
授权域(如果提供的话)
填写用户名和密码的区域
当连接到NTLM授权模式的服务器时,还会包含一个填写domain的区域
一个说明信息,指明凭据是否将会被以明文方式发送(例如:“只有当使用基于非SSL的基本授权模式时才会以明文方式发送”)
如果你想改变它的外观,你必须继承ASIHTTPRequest,并重写showAuthenticationDialog来显示你自己的对话框或ASIAuthenticationDialog子类。
在服务器请求凭据前向服务器发送凭据
IMPORTANT从1.8.1开始,使用基本授权模式的request时,这个特性的行为改变了。你可能需要修改你的代码。
在第一次生成request时,ASIHTTPRequest可以先向服务器发送凭据(如果有的话),而不是等服务器要求提供凭据时才提供凭据。这个特性可以提高使用授权的程序的执行效率,因为这个特性避免了多余的request。
对于基本授权模式,要触发这个行为,你必须手动设置request的authenticationScheme为kCFHTTPAuthenticationSchemeBasic:
1 | [request setAuthenticationScheme :( NSString *)kCFHTTPAuthenticationSchemeBasic]; |
在以下情况下,你也许想要禁用这个特性:
你的程序可能会一次使用一系列凭据来与服务器对话
安全性对于你的程序来说非常重要。使用这个特性是相对不安全的,因为你不能在凭据被发送前验证你是否连接到了正确的服务器。
要禁用这个特性,这样做:
1 | [request setShouldPresentCredentialsBeforeChallenge : NO ]; |
相关文章推荐
- ASIHTTPRequest-直接读取磁盘数据流的请求体
- ASIHTTPRequest-直接读取磁盘数据流的请求体
- ASIHTTPRequest-直接读取磁盘数据流的请求体
- iOS开发ASIHTTPRequest直接读取磁盘数据流的请求体的内容
- ASIHTTPRequest-直接读取磁盘数据流的请求体
- ios开发之ASIHTTPRequest-直接读取磁盘数据流的请求体
- ASIHTTPRequest-直接读取磁盘数据流的请求体
- iOS开发ASIHttpRequest介绍(八)-- ASIHTTPRequest直接读取磁盘数据流请求体
- iOS开发ASIHTTPRequest直接读取磁盘数据流请求体
- iOS开发ASIHTTPRequest直接读取磁盘数据流请求体【9】
- iOS开发ASIHTTPRequest直接读取磁盘数据流请求体
- ASIHTTPRequest-数据压缩
- ios开发之asihttprequest数据离线缓存与读取
- 【转】ASIHTTPRequest-数据压缩
- ASIHTTPRequest-数据压缩
- ASIHTTPRequest数据压缩
- ios--- ios开发之asihttprequest数据离线缓存与读取
- iOS开发ASIHttpRequest介绍(六)-- ASIHTTPRequest数据压缩
- Java读取HttpServletRequest的post数据流
- iOS开发ASIHTTPRequest数据压缩