IOS ASIHttp库的使用总结

下载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

 

类库的依赖关系:

ASIHTTP类库依赖于以下5个框架或库:

CFNetwork, SystemConfiguration, MobileCoreServices, CoreGraphics 和 libz1.2.3。

及一个网络操作源码:

Reachability.h (在源码的 External/Reachability 目录下)

Reachability.m (在源码的 External/Reachability 目录下)

 

库文件:

认证对话框

ASIAuthenticationDialog.h
ASIAuthenticationDialog.m
缓存代理接口
ASICacheDelegate.h
typedef enum _ASICachePolicy {
	
	// 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'
	ASIUseDefaultCachePolicy = 0,
	
	// Tell the request not to read from the cache
	ASIDoNotReadFromCacheCachePolicy = 1,
	
	// The the request not to write to the cache
	ASIDoNotWriteToCacheCachePolicy = 2,
	
	// Ask the server if there is an updated version of this resource (using a conditional GET) ONLY when the cached data is stale
	ASIAskServerIfModifiedWhenStaleCachePolicy = 4,
	
	// Always ask the server if there is an updated version of this resource (using a conditional GET)
	ASIAskServerIfModifiedCachePolicy = 8,
	
	// 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
	ASIOnlyLoadIfNotCachedCachePolicy = 16,
	
	// 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)
	ASIDontLoadCachePolicy = 32,
	
	// 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.
	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             当前请求不读取缓存数据。

ASIDoNotWriteToCacheCachePolicy                        2             当前请求不写缓存数据。
ASIAskServerIfModifiedWhenStaleCachePolicy      4            默认缓存行为,request会先判断是否存在缓存数据,如果没有再进行网络请求。 如果存在缓存数据,并且数据没有过期,则使用缓存。如果存在缓存数据,但已经过期,request会先进行网络请求,判断服务器版本与本地版本是否一样,如果一样,则使用缓存。如果服务器有新版本,会进行网络请求,并更新本地缓存。(使用GET请求时有效)
ASIAskServerIfModifiedCachePolicy                         8             每次请求都会 去服务器判断是否有更新。(使用GET请求时有效)
ASIOnlyLoadIfNotCachedCachePolicy                     16          只要有缓存,就读取缓存数据而不管数据是否过期。直到请求的数据不在缓冲中时,才去服务器获取。
ASIDontLoadCachePolicy                                           32          只要有缓存,就读取缓存数据而不管数据是否过期。如果缓存中没有数据,则停止,不向服务器请求。
ASIFallbackToCacheIfLoadFailsCachePolicy         64          这个选项经常被用来与其它选项组合使用。请求失败时,使用本地缓存数据,如果使用本地缓冲,请求会成功不会引发错误(这个在处理异常时非常有用)
 
对代理方法可以见下载代理源码。里机的实现是很好的学习例子。是继承ASICacheDelegate的。
ASIDownloadCache.h
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]]; 



数据压缩:支持对bytes和流数据,文件数据压缩
ASIDataCompressor.h
ASIDataCompressor.m
数据解压:支持对bytes和流数据,文件数据压缩
ASIDataDecompressor.h
ASIDataDecompressor.m
 
进度条代里:通过这代里设置,可以实现进度条效果。如上传下载进度
ASIProgressDelegate.h
将数据输为数据流进行操作。
ASIInputStream.h
ASIInputStream.m
存放ASI调试开关宏定义
ASIHTTPRequestConfig.h
 
请求响应代理:
ASIHTTPRequestDelegate.h
@protocol ASIHTTPRequestDelegate <NSObject>

@optional

// These are the default delegate methods for request status
// You can use different ones by setting didStartSelector / didFinishSelector / didFailSelector
- (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;

// 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
- (void)request:(ASIHTTPRequest *)request didReceiveData:(NSData *)data;

// 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])
- (void)authenticationNeededForRequest:(ASIHTTPRequest *)request;
- (void)proxyAuthenticationNeededForRequest:(ASIHTTPRequest *)request;

@end

- (void)requestStarted:(ASIHTTPRequest *)request;
当开始发起请求时触发,request为当前请求的上下文。
 
- (void)request:(ASIHTTPRequest *)request didReceiveResponseHeaders:(NSDictionary *)responseHeaders;
当请求后收到响应头时触发,request为请求的上下文,responseHeaders存放HTTP响应的头域
 
对头域的提取可以使用如下方法:
[request responseStatusCode];
[[request responseHeaders] objectForKey:@"X-Powered-By"];
 [request responseEncoding]; 


 
- (void)request:(ASIHTTPRequest *)request willRedirectToURL:(NSURL *)newURL;
当请求一URL时,服务器响应重定向,跳转到新URL前触发。
 
- (void)requestRedirected:(ASIHTTPRequest *)request;
重定向到新URL完成后触发。
 
- (void)requestFinished:(ASIHTTPRequest *)request;
本次请求完成功后触发。即一次有效会话完成。
 
- (void)requestFailed:(ASIHTTPRequest *)request;
请求失败时触发。可以能过NSError* err = [response error]得到错误信息。
 
- (void)request:(ASIHTTPRequest *)request didReceiveData:(NSData *)data;
单次有接收数据时触发。(如果数据过长就会分块进行传输)这个也可以自己来实现进度条效果。
 
例子:
-(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 !");
    }];
    
    
    
    [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];//写入当前数据块
        }
    }];
    
    [request startAsynchronous];
}
红色部份就是回调。
 
- (void)authenticationNeededForRequest:(ASIHTTPRequest *)request;
当本次请求后,服务响应要求客户端进行认证时触发。
 
- (void)proxyAuthenticationNeededForRequest:(ASIHTTPRequest *)request;
请求需要代理认证时触发。
 
通常这个代理类只有在开启HTTP异步时才有效,同步情况下不会触发这些回调。
 
HTTP请求类:(核心文件了对IOS网络通导进行了一层封装)
ASIHTTPRequest.h
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:@http://www.baidu.com];
    ASIHTTPRequest* request = [ASIHTTPRequest requestWithURL:url];   
    request.delegate = self;
    [request startAsynchronous];//异步请求
其中红色部分表明要实现代理的类的实例。因为放在调用者中进行实现回调代理,所以这里用self。当然也可以自己写一个专门的实现代理的类来处理。
回调方式一:使用代理类来实现ASIHTTPRequestDelegate.h中的方法。
设置这一句之后就可以把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给我们提供了多种回调方式,任由开发者进行发挥。
回调方式二:
使用OC本身的block特性来进行提定。使用这种回调不需要指定delegate类。但个人认为这种方式跟踪起来看的有点费劲(个人习惯)。
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;

当开始发起请求时触发,request为当前请求的上下文。与- (void)requestStarted:(ASIHTTPRequest *)request;回调一样

 

- (void)setHeadersReceivedBlock:(ASIHeadersBlock)aReceivedBlock;

当请求后收到响应头时触发,request为请求的上下文,responseHeaders存放HTTP响应的头域,与
- (void)request:(ASIHTTPRequest *)request didReceiveResponseHeaders:(NSDictionary *)responseHeaders;的回调一样。
 

- (void)setCompletionBlock:(ASIBasicBlock)aCompletionBlock;

本次请求完成功后触发。即一次有效会话完成。与- (void)requestFinished:(ASIHTTPRequest *)request;回调一样。

- (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)request:(ASIHTTPRequest *)request didReceiveData:(NSData *)data;回调一样。

 

- (void)setAuthenticationNeededBlock:(ASIBasicBlock)anAuthenticationBlock;

当本次请求后,服务响应要求客户端进行认证时触发。与- (void)authenticationNeededForRequest:(ASIHTTPRequest *)request;回调一样。

 

- (void)setProxyAuthenticationNeededBlock:(ASIBasicBlock)aProxyAuthenticationBlock;

请求需要代理认证时触发。与- (void)proxyAuthenticationNeededForRequest:(ASIHTTPRequest *)request;回调一样。

 

- (void)setRequestRedirectedBlock:(ASIBasicBlock)aRedirectBlock;

重定向到新URL完成后触发。与- (void)requestRedirected:(ASIHTTPRequest *)request;回调一样。
 
回调方式三:通过选择器实现(SEL)有点像DELPHI中的事件回调的实现。
SEL didStartSelector;
 
SEL didReceiveResponseHeadersSelector;
 
SEL willRedirectSelector;
 
SEL didFinishSelector;
 
SEL didFailSelector;
 
SEL didReceiveDataSelector;
 
三种回调任先其一来进行相应的应用开发。当然大家也可以试试三种都设置后看优先触发哪种回调。
 
关于异步请求,响应的请求判断,通常情况下,并发数个请求,每个请求响应的先后顺序都不一样,哪么如何能正确的处理请求所对应的响应呢。方法有三:
 
1、使用回调方式一,通过回调方法中的request(上下文)中的userinfo这个来设置相应的请求ID或唯一身份。待响应回调中通过上下文(request)取出相应的userinfo来进行判断是哪个具体的请求。
2、使用方式二和方式三的回调方式,因为该回调是指定在当前对应的request中的。创建不同的实例时就可以通过实例的方式进行区分。
3、使用子类来定义相应的业务请求区分。
 
http访问代理设置:
    request setProxyAuthenticationScheme:(NSString *);
    request setProxyCredentials:(NSDictionary *);
    request setProxyDomain:(NSString *);
    request setProxyHost:(NSString *);
    request setProxyPassword:(NSString *);
    request setProxyPort:(int);
    request setProxyType:(NSString *);
    request setProxyUsername:(NSString *); 
也可以通过PAC(Proxy Auto Config)文件来设置代理:
[request setPACurl:[NSURL URLWithString:@ "file:///Users/xxx/Desktop/proxys.pac" ]];
 
取消请求      
对于异步操作时,可能大家也想到了,过程中的请求是否可以取消的问题。
对于异步操作是有取消,同步请求是没有取消的。
 
调用[request cancel];就可以进行取消正在进行的请求,取消时会触发请求失败的回调方法。如果在取消过程中不想触发该回调,可以将实例进行设置。如下:
[request clearDelegatesAndCancel];
 
如果使用ASINetworkQueue队列来管理请求实例。
取消所有请求,使用 [queue cancelAllOperations];
 
别外需要注意的:
队列请求中需要注意的是,如果你取消了一个请求,队列会自动取消其它所有请求。
[[[networkqueue operations]objectAtIndex:1] cancel]; 如果这样操作会把所有的请求都取消了。
如果只需要想要的请求怎么办。只需要设置:[ queue setShouldCancelAllRequestsOnFailure:NO ];即可。设置完成后,调用[[[networkqueue operations]objectAtIndex:1] cancel];就会把第二个请求取消了。而其它请求仍在进行。
 
 
异步下载代码段:
-(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 = [[[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]);

 
表单数据请求:
ASIFormDataRequest.h
ASIFormDataRequest.m
 
对Request的扩展,主要处理页面的表单数据的提交。通常适用于"POST"和"PUT"操作。
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"调用:[request setRequestMethod:@"PUT"];即可。

 

上传代码段:

-(void)btnuploadclicked
{
    NSString* ps = @"test";
    NSURL* serverurl = [NSURL URLWithString:@http://xxxxxxxxx];
    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
 
查看源文件可以看出ASINetworkQueue可以看作一个线程池,可以设置线程挂起和恢复。而ASIHttpRequest就是一个操作NSOperation ,其实可以当作为一个任务,这样就有点像线程池任务队列了。
每个ASIhttpRequest中实现了自己的-(void)main方法。
从该方法中可以看到最终的请求是使用CFNewWork中的CFHTTPMessageCreateRequest
// 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需要谨慎。

 

你可能感兴趣的:(IOS ASIHttp库的使用总结)