下载ASIHTTPRequest:
- Github project page: http://github.com/pokeb/asi-http-request/tree
- Download the latest version: http://github.com/pokeb/asi-http-request/tarball/master
- License (BSD): http://github.com/pokeb/asi-http-request/tree/master/LICENSE
- Google Group: http://groups.google.com/group/asihttprequest
- Lighthouse bug base: http://allseeing-i.lighthouseapp.com/projects/27881/home
- 相关资料 http://allseeing-i.com/ASIHTTPRequest/How-to-use - Using blocks
Blocks Programming Topics - Object and Block Variables
类库的依赖关系:
ASIHTTP类库依赖于以下5个框架或库:
CFNetwork, SystemConfiguration, MobileCoreServices, CoreGraphics 和 libz1.2.3。
及一个网络操作源码:
Reachability.h (在源码的 External/Reachability 目录下)
Reachability.m (在源码的 External/Reachability 目录下)
库文件:
认证对话框
ASIAuthenticationDialog.m
- typedef enum _ASICachePolicy {
- <span style="color:#009900;">// The default cache policy. When you set a request to use this, it will use the cache's defaultCachePolicy
- // ASIDownloadCache's default cache policy is 'ASIAskServerIfModifiedWhenStaleCachePolicy'
- </span> ASIUseDefaultCachePolicy = 0,
- <span style="color:#009900;">// Tell the request not to read from the cache
- </span> ASIDoNotReadFromCacheCachePolicy = 1,
- <span style="color:#009900;">// The the request not to write to the cache
- </span> ASIDoNotWriteToCacheCachePolicy = 2,
- <span style="color:#009900;">// Ask the server if there is an updated version of this resource (using a conditional GET) ONLY when the cached data is stale
- </span> ASIAskServerIfModifiedWhenStaleCachePolicy = 4,
- <span style="color:#009900;">// Always ask the server if there is an updated version of this resource (using a conditional GET)
- </span> ASIAskServerIfModifiedCachePolicy = 8,
- <span style="color:#009900;">// If cached data exists, use it even if it is stale. This means requests will not talk to the server unless the resource they are requesting is not in the cache
- </span> ASIOnlyLoadIfNotCachedCachePolicy = 16,
- <span style="color:#009900;">// If cached data exists, use it even if it is stale. If cached data does not exist, stop (will not set an error on the request)
- </span> ASIDontLoadCachePolicy = 32,
- <span style="color:#009900;">// Specifies that cached data may be used if the request fails. If cached data is used, the request will succeed without error. Usually used in combination with other options above.
- </span> ASIFallbackToCacheIfLoadFailsCachePolicy = 64
- } ASICachePolicy;
枚举类型中的策略值:
策略可以进行组合
如:
[request setCachePolicy:ASIAskServerIfModifiedCachePolicy|ASIFallbackToCacheIfLoadFailsCachePolicy|ASIDoNotWriteToCacheCachePolicy];
但注意:
调用[ASIHTTPRequest clearSession]将会删除任何使用ASICacheForSessionDurationCacheStoragePolicy策略的缓存数据。
使用ASICachePermanentlyCacheStoragePolicy,缓存的相应数据会被永久存储。要使用这个存储策略,向request设置:
- ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
- [request setCacheStoragePolicy:ASICachePermanentlyCacheStoragePolicy];
要手动清除cache,调用函数clearCachedResponsesForStoragePolicy:,传入要清除的cache数据的存储策略:
- [[ASIDownloadCache sharedCache] clearCachedResponsesForStoragePolicy:ASICachePermanentlyCacheStoragePolicy];
ASIUseDefaultCachePolicy 0 默认情况下的缓存策略(它不能与其它策略组合使用)
ASIDoNotReadFromCacheCachePolicy 1 当前请求不读取缓存数据。
ASIAskServerIfModifiedWhenStaleCachePolicy 4 默认缓存行为,request会先判断是否存在缓存数据,如果没有再进行网络请求。 如果存在缓存数据,并且数据没有过期,则使用缓存。如果存在缓存数据,但已经过期,request会先进行网络请求,判断服务器版本与本地版本是否一样,如果一样,则使用缓存。如果服务器有新版本,会进行网络请求,并更新本地缓存。(使用GET请求时有效)
ASIDownloadCache.m
- 它对Get请求的响应数据进行缓存(被缓存的数据必需是成功的200请求):
- [ASIHTTPRequest setDefaultCache:[ASIDownloadCache sharedCache]];
- 当设置缓存策略后,所有的请求都被自动的缓存起来。
- 另外,如果仅仅希望某次请求使用缓存操作,也可以这样使用:
- ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
- [request setDownloadCache:[ASIDownloadCache sharedCache]];
- 多种的缓存并存
- 仅仅需要创建不同的ASIDownloadCache,并设置缓存所使用的路径,并设置到需要使用的request实例中:
- ASIDownloadCache *cache = [[[ASIDownloadCache alloc] init] autorelease];
- [cache setStoragePath:@"/Users/ben/Documents/Cached-Downloads"];
- [self setMyCache:cache];
- ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
- [request setDownloadCache:[self myCache]];
ASIDataCompressor.h
ASIDataCompressor.m
ASIDataDecompressor.h
ASIInputStream.m
ASIHTTPRequestDelegate.h
- @protocol ASIHTTPRequestDelegate <NSObject>
- @optional
- <span style="color:#009900;">// These are the default delegate methods for request status
- // You can use different ones by setting didStartSelector / didFinishSelector / didFailSelector
- </span>- (void)requestStarted:(ASIHTTPRequest *)request;
- - (void)request:(ASIHTTPRequest *)request didReceiveResponseHeaders:(NSDictionary *)responseHeaders;
- - (void)request:(ASIHTTPRequest *)request willRedirectToURL:(NSURL *)newURL;
- - (void)requestFinished:(ASIHTTPRequest *)request;
- - (void)requestFailed:(ASIHTTPRequest *)request;
- - (void)requestRedirected:(ASIHTTPRequest *)request;
- <span style="color:#009900;">// When a delegate implements this method, it is expected to process all incoming data itself
- // This means that responseData / responseString / downloadDestinationPath etc are ignored
- // You can have the request call a different method by setting didReceiveDataSelector
- </span>- (void)request:(ASIHTTPRequest *)request didReceiveData:(NSData *)data;
- <span style="color:#009900;">// If a delegate implements one of these, it will be asked to supply credentials when none are available
- // The delegate can then either restart the request ([request retryUsingSuppliedCredentials]) once credentials have been set
- // or cancel it ([request cancelAuthentication])
- </span>- (void)authenticationNeededForRequest:(ASIHTTPRequest *)request;
- - (void)proxyAuthenticationNeededForRequest:(ASIHTTPRequest *)request;
- @end
- (void)requestStarted:(ASIHTTPRequest *)request;
- [request responseStatusCode];
- [[request responseHeaders] objectForKey:@"X-Powered-By"];
- [request responseEncoding];
- -(void)Down
- {
- NSString* paths = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)objectAtIndex:0];
- NSString* filename = @"fileOk.zip";
- NSString* filepath = [paths stringByAppendingPathComponent:filename];
- //创建路径及空文件
- bool ret = [[NSFileManager defaultManager] createFileAtPath:filepath contents:nil attributes:nil];
- NSFileHandle* fhandle; //文件句柄
- __block uint fileszie = 0;//初始化文件大小
- if (ret) {
- fhandle = [NSFileHandle fileHandleForWritingAtPath:filepath];
- }
- NSURL* url = [NSURL URLWithString:@"http://dd2.pc6.com/xy1/6000ICO.rar"];
- ASIHTTPRequest* request = [ASIHTTPRequest requestWithURL:url];
- [request setShouldContinueWhenAppEntersBackground:YES];
- [request setDownloadProgressDelegate:progressview];
- [request setCompletionBlock:^{
- NSLog(@"Completed!");
- assert(fhandle);
- [fhandle closeFile];
- }];
- [request setFailedBlock:^{
- NSLog(@"download failed !");
- }];
- <span style="color:#ff0000;">[request setDataReceivedBlock:^(NSData* data){
- fileszie += data.length;
- NSLog(@"recive total : %@",[NSString stringWithFormat:@"%.1f K",fileszie/1000.0]);
- if (fhandle != nil)
- {
- [fhandle seekToEndOfFile];//移到末端进行追加
- [fhandle writeData:data];//写入当前数据块
- }
- }];
- </span>
- [request startAsynchronous];
- }
ASIHTTPRequest.m
- NSURL* url = [NSURL URLWithString:@"http://www.baidu.com"];
- ASIHTTPRequest* request = [ASIHTTPRequest requestWithURL:url];
- //[request startSynchronous];//use 同步请求
- NSError* err = [request error];
- assert(!err);
- NSString* responsestr = [request responseString];
异步请求:
- NSURL* url = [NSURL URLWithString:@<a href="http://www.baidu.com">http://www.baidu.com</a>];
- ASIHTTPRequest* request = [ASIHTTPRequest requestWithURL:url];
- <span style="color:#ff0000;">request.delegate = self;
- </span> [request startAsynchronous];//异步请求
设置这一句之后就可以把ASIHTTPRequestDelegate.h中的方法放到调用者中进行实现这些回调了。如:
- //异步回调
- -(void)requestFailed:(ASIHTTPRequest *)request
- {
- NSError* err = [request error];
- NSLog(@"error info = %@",err.userInfo);
- }
- -(void)requestFinished:(ASIHTTPRequest *)request
- {
- NSString* result = [request responseString];
- NSLog(@"Finised : %@",result);
- }
- -(void)request:(ASIHTTPRequest *)request didReceiveResponseHeaders:(NSDictionary *)responseHeaders
- {
- NSLog(@"rq : %@",responseHeaders);
- }
上面的回调使用的是代理类的方式进行。对于异步请求,ASIHTTPRequest给我们提供了多种回调方式,任由开发者进行发挥。
- NSURL* url = [NSURL URLWithString:@"http://www.baidu.com"];
- ASIHTTPRequest* request = [ASIHTTPRequest requestWithURL:url];
- [request setCompletionBlock:^{
- NSString* restr = [request responseString];
- //NSData* data = [request responseData];
- NSLog(@"%@",restr);
- }];
- [request setFailedBlock:^{
- NSError* err = [request error];
- NSLog(@"err = %@",err.userInfo);
- }];
- [request startAsynchronous];
一共有的回调定义(即函数指针)
- #if NS_BLOCKS_AVAILABLE
- typedef void (^ASIBasicBlock)(void);
- typedef void (^ASIHeadersBlock)(NSDictionary *responseHeaders);
- typedef void (^ASISizeBlock)(long long size);
- typedef void (^ASIProgressBlock)(unsigned long long size, unsigned long long total);
- typedef void (^ASIDataBlock)(NSData *data);
- #endif
- (void)setStartedBlock:(ASIBasicBlock)aStartedBlock;
- (void)setHeadersReceivedBlock:(ASIHeadersBlock)aReceivedBlock;
- (void)setCompletionBlock:(ASIBasicBlock)aCompletionBlock;
- (void)setFailedBlock:(ASIBasicBlock)aFailedBlock;
- (void)setBytesReceivedBlock:(ASIProgressBlock)aBytesReceivedBlock;
当接收到字节数据时触发。
- (void)setBytesSentBlock:(ASIProgressBlock)aBytesSentBlock;
当有数据发送到服务器时触发。
- (void)setDownloadSizeIncrementedBlock:(ASISizeBlock)aDownloadSizeIncrementedBlock;
在进行下载前,需要动态增长下载块大小时触发。
- (void)setUploadSizeIncrementedBlock:(ASISizeBlock)anUploadSizeIncrementedBlock;
在上传数据前,需要动态增长数据块大小时触发。
- (void)setDataReceivedBlock:(ASIDataBlock)aReceivedBlock;
- (void)setAuthenticationNeededBlock:(ASIBasicBlock)anAuthenticationBlock;
- (void)setProxyAuthenticationNeededBlock:(ASIBasicBlock)aProxyAuthenticationBlock;
- (void)setRequestRedirectedBlock:(ASIBasicBlock)aRedirectBlock;
SEL didReceiveResponseHeadersSelector;
SEL willRedirectSelector;
SEL didFinishSelector;
SEL didFailSelector;
SEL didReceiveDataSelector;
- request setProxyAuthenticationScheme:(NSString *);
- request setProxyCredentials:(NSDictionary *);
- request setProxyDomain:(NSString *);
- request setProxyHost:(NSString *);
- request setProxyPassword:(NSString *);
- request setProxyPort:(int);
- request setProxyType:(NSString *);
- request setProxyUsername:(NSString *);
[request setPACurl:[NSURLURLWithString:@
"file:///Users/xxx/Desktop/proxys.pac"
]];
- -(void)downbtnclicked
- {
- NSString* paths = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES)objectAtIndex:0];
- paths = [paths stringByAppendingFormat:@"/down.zip"];
- NSURL* url = [NSURL URLWithString:@"http://dd2.pc6.com/xy1/6000ICO.rar"];
- ASIHTTPRequest* rq = [ASIHTTPRequest requestWithURL:url];
- //[rq setShouldContinueWhenAppEntersBackground:YES];//退到后台仍运行
- [rq setTimeOutSeconds:20];
- [rq setDownloadDestinationPath:paths];//设置下载存放路径
- NSLog(@"paths = %@",paths);
- [rq setDownloadProgressDelegate:progressview];//设置下载进度,这里progrssview为UIProgressView
- [rq setFailedBlock:^{
- NSError* err = [rq error];
- NSLog(@"errinfo = %@",err.userInfo);
- }];
- [rq startAsynchronous];
- }
cookie的支持
如果Cookie存在的话,会把这些信息放在NSHTTPCookieStorage容器中共享,并供下次使用。
你可以用[ ASIHTTPRequest setSessionCookies:nil ] ; 清空所有Cookies。
当然,你也可以取消默认的Cookie策略,而使自定义的Cookie:
//Create a cookie
NSDictionary *properties = [[[NSMutableDictionaryalloc]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 = [[[NSHTTPCookiealloc] initWithProperties:properties]autorelease];
//This url will return the value of the 'ASIHTTPRequestTestCookie' cookie
request = [ASIHTTPRequestrequestWithURL:url];
[request setUseCookiePersistence:NO];
[request setRequestCookies:[NSMutableArray arrayWithObject:cookie]];
[request startSynchronous];
//Should be: I have 'Test Value' as the value of 'ASIHTTPRequestTestCookie'
NSLog(@
"%@"
,[requestresponseString]);
|
ASIFormDataRequest.h
ASIFormDataRequest.m
- ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
- [request setPostValue:@"15967287719" forKey:@"phonenums"];
- [request setPostValue:@"男" forKey:@"sex"];
- [request setFile:@"/Users/xxx/Desktop/avatar.jpg" forKey:@"photo"];
- [request addData:imageData withFileName:@"avatar.jpg" andContentType:@"image/jpeg" forKey:@"photos"];
- 默认为"POST"方式。如果想改为"PUT"调用:<code class="java plain">[request setRequestMethod:@</code><code class="java string">"PUT"</code><code class="java plain">];即可。</code>
上传代码段:
- -(void)btnuploadclicked
- {
- NSString* ps = @"test";
- NSURL* serverurl = [NSURL URLWithString:@<a href="http://xxxxxxxxx">http://xxxxxxxxx</a>];
- formrequest = [ASIFormDataRequest requestWithURL:serverurl];
- NSStringEncoding encoding = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingMacChineseSimp);
- [formrequest setStringEncoding:encoding];
- [self printfBytes:ps Encoding:encoding];
- [formrequest setPostValue:ps forKey:@"title"];
- [formrequest setFile:@"/user/ffsh/Desktop/test.zip" forKey:@"attch"];
- [formrequest setDelegate:self];
- [formrequest setDidFinishSelector:@selector(OnRequestFinished)];
- [formrequest setDidFailSelector:@selector(OnRequestFaided)];
- [formrequest startAsynchronous];
- }
ASINetworkQueue.h
ASINetworkQueue.m
- // Create a new HTTP request.
- request = CFHTTPMessageCreateRequest(kCFAllocatorDefault, (CFStringRef)[self requestMethod], (CFURLRef)[self url], [self useHTTPVersionOne] ? kCFHTTPVersion1_0 : kCFHTTPVersion1_1);
- if (!request) {
- [self failWithError:ASIUnableToCreateRequestError];
- return;
- }
在最后执行请求:
- // If we immediately have access to proxy settings, start the request
- // Otherwise, we'll start downloading the proxy PAC file, and call startRequest once that process is complete
- if ([self configureProxies]) {
- [self startRequest];
- }
如果大家对NSOperationQueue和NSOperation使用不熟悉的,可以学习一下,再来看这两个文件,就简单些了。
多个请求例子:
- -(void)goclicked
- {
- if(!fm)
- {
- fm = [NSFileManager defaultManager];
- }
- NSString* paths = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)objectAtIndex:0];
- //NSLog(@"paths = %@",paths);
- NSString* filenames = @"filedown.zip";
- NSString* filepath = [paths stringByAppendingPathComponent:filenames];
- bool ret = [fm createFileAtPath:filepath contents:nil attributes:nil];
- NSFileHandle* fhandle;
- __block uint fSize1 = 0;
- if (ret) {
- fhandle = [NSFileHandle fileHandleForWritingAtPath:filepath];
- }
- NSString* filename2 = @"file.zip";
- NSString* filepath2 = [paths stringByAppendingPathComponent:filename2];
- ret = [fm createFileAtPath:filepath2 contents:nil attributes:nil];
- NSFileHandle* fhd;
- __block uint fSize2 = 0;
- if (ret) {
- fhd = [NSFileHandle fileHandleForWritingAtPath:filepath2];
- }
- NSURL* url = [NSURL URLWithString:@"http://dd2.pc6.com/xy1/6000ICO.rar"];
- NSURL* url2 = [NSURL URLWithString:@"http://dd2.pc6.com/xy1/6000ICO.rar"];
- if (!networkqueue) {
- networkqueue = [[ASINetworkQueue alloc]init];
- }
- failed = NO;
- [networkqueue reset];//清空队列
- [networkqueue setDownloadProgressDelegate:totalprogressview];
- [networkqueue setShowAccurateProgress:YES];//进步精确显示
- [networkqueue setDelegate:self];
- ASIHTTPRequest* request = [ASIHTTPRequest requestWithURL:url];
- [request setShouldContinueWhenAppEntersBackground:YES];
- [request setDownloadProgressDelegate:progressview];
- [request setUserInfo:[NSDictionary dictionaryWithObject:filenames forKey:@"TargetPath"]];
- [request setCompletionBlock:^{
- NSLog(@"%@ Completed!",filenames);
- assert(fhandle);
- [fhandle closeFile];
- }];
- [request setFailedBlock:^{
- NSLog(@"%@ download failed !",filenames);
- }];
- [request setDataReceivedBlock:^(NSData* data){
- fSize1 += data.length;
- [progressone setText:[NSString stringWithFormat:@"%.1f K",fSize1/1000.0]];
- [totalsize setText:[NSString stringWithFormat:@"%.0f%%",totalprogressview.progress*100]];
- if (fhandle != nil)
- {
- [fhandle seekToEndOfFile];
- [fhandle writeData:data];
- }
- NSLog(@"%@:%u",filenames,data.length);
- }];
- [networkqueue addOperation:request];
- request = [ASIHTTPRequest requestWithURL:url2];
- [request setShouldContinueWhenAppEntersBackground:YES];
- [request setDownloadProgressDelegate:progress];
- [request setUserInfo:[NSDictionary dictionaryWithObject:filename2 forKey:@"TargetPath"]];
- [request setCompletionBlock:^{
- NSLog(@"%@ Completed!",filename2);
- assert(fhd);
- [fhd closeFile];
- }];
- [request setFailedBlock:^{
- NSLog(@"%@ download failed !",filename2);
- }];
- [request setDataReceivedBlock:^(NSData* data){
- fSize2 += data.length;
- [progresstwo setText:[NSString stringWithFormat:@"%d b",fSize2/*/1024.0*/]];
- [totalsize setText:[NSString stringWithFormat:@"%.0f%%",totalprogressview.progress*100]];
- if (fhd != nil)
- {
- [fhd seekToEndOfFile];
- [fhd writeData:data];
- }
- }];
- [networkqueue addOperation:request];
- [networkqueue go];
- }
请求中止,或应该用退出前,最好先把所有请求取消。加强对内存回的安全性。
另外:ASI目前团队已不维护ASI库,在后续的SDK4.5及IOS6.0的版本里,很多接口已被废弃。所在在高版本下使用ASI需要谨慎。