ASIHTTP 框架,同步、 异步请求、 上传 、 下载
ASIHTTPRequest詳解
ASIHTTPRequest?是一款極其強勁的?HTTP?訪問開源項目。讓簡單的?API?完成復雜的功能,如:異步請求,隊列請求,GZIP?壓縮,緩存,斷點續傳,進度跟蹤,上傳文件,HTTP?認證。在新的版本中,還加入了?Objective-C?閉包?Block?的支持,讓我們的代碼加輕簡靈活。
?
????下面就舉例說明它的?API?用法。
?
發起一個同步請求
?
????同步意為著線程阻塞,在主線程中使用此方法會使應用Hang住而不響應任何用戶事件。所以,在應用程序設計時,大多被用在專門的子線程增加用戶體驗,或用異步請求代替(下面會講到)。
? ????-?(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];
? ??????}
? ????}
?
用?requestWithURL?快捷方法獲取?ASIHTTPRequest?的一個實例
startSynchronous?方法啟動同步訪問
由于是同步請求,沒有基于事件的回調方法,所以從?request的error?屬性獲取錯誤信息
responseString,為請求的返回?NSString?信息
創建一個異步請求
?
????異步請求的好處是不阻塞當前線程,但相對于同步請求略為復雜,至少要添加兩個回調方法來獲取異步事件。下面異步請求代碼完成上面同樣的一件事情:
? -?(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",并用?startAsynchronous?來啟動網絡請求
在這里實現了兩個?delegate?的方法,當數據請求成功時會調用?requestFinished,請求失敗時(如網絡問題或服務器內部錯誤)會調用?requestFailed。
隊列請求
?
????提供了一個對異步請求更加精準豐富的控制。如:可以設置在隊列中同步請求的連接數。往隊列里添加的請求實例數大于?maxConcurrentOperationCount?時,請求實例將被置為等待,直到前面至少有一個請求完成并出列才被放到隊列里執行。這也適用于當我們有多個請求需求按順序執行的時候(可能是業務上的需要,也可能是軟件上的調優),僅僅需要把?maxConcurrentOperationCount?設為“1”。
? -?(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
? }
?
? -?(void)requestDone:(ASIHTTPRequest?*)request
? {
? ???NSString?*response?=?[request?responseString];
? }
?
? -?(void)requestWentWrong:(ASIHTTPRequest?*)request
? {
? ???NSError?*error?=?[request?error];
? }
?
創建?NSOperationQueue,這個?Cocoa?架構的執行任務(NSOperation)的任務隊列。我們通過?ASIHTTPRequest.h?的源碼可以看到,此類本身就是一個?NSOperation?的子類。也就是說它可以直接被放到"任務隊列"中并被執行。上面的代碼除了隊列的創建與添加操作外,其它代碼與上一例一樣。
?
隊列異步請求中中獲取或識別不同request小技巧
?
可以設置一個上下文(userInfo)到?request?對象中,當請求響應完后可以通過訪問?request?對象的?userInfo?獲取里面的信息
為每一個請求實例設置不同的?setDidFinishSelector?/?setDidFailSelector?的回調方法
子類化?ASIHTTPRequest,重寫?requestFinished:?與?failWithProblem:?方法
ASINetworkQueues,?它的delegate提供更為豐富的功能
?
????提供的更多的回調方法如下:
?
requestDidStartSelector,請求發起時會調此方法,你可以在此方法中跟據業務選擇性的設置?request?對象的?deleaget
requestDidReceiveResponseHeadersSelector,當接受完響應的?Header?后設計此方法,這個對下載大數據的時候相當有用,你可以在方法里做更多業務上的處理
requestDidFinishSelector,請求并響應成功完成時調用此方法
requestDidFailSelector,請求失敗
queueDidFinishSelector,整個隊列里的所有請求都結束時調用此方法
????它是?NSOperationQueues?的擴展,小而強大。但也與它的父類略有區別。如,僅添加到隊列中其實并不能執行請求,只有調用[??queue?g?o?]才會執行;一個正在運行中的隊列,并不需要重復調用[??queue?go??]。默認情況下,隊列中的一個請求如果失敗,它會取消所有未完成的請求。可以設置[??queue?setShouldCancelAllRequestsOnFailure:NO??]來修正。
?
取消異步請求
?
????首先,同步請求是不能取消的。
?
????其次,不管是隊列請求,還是簡單的異步請求,全部調用[?request?cancel?]來取消請求。取消的請求默認都會按請求失敗處理,并調用請求失敗delegate。
????如果不想調用delegate方法,則設置:[?request?clearDelegatesAndCancel];
?
????隊列請求中需要注意的是,如果你取消了一個請求,隊列會自動取消其它所有請求。如果只想取消一個請求,可以設置隊列:[?queue?setShouldCancelAllRequestsOnFailure:NO?];?如果想明確取消所有請求:[?queue?cancelAllOperations?];
?
安全的內存回收建議
?
????request并沒有retain你的delegate,所以在沒有請求完的時候釋放了此delegate,需要在dealloc方法里先取消所有請求,再釋放請求實例,如:
? -?(void)dealloc
? {
? ???[request?clearDelegatesAndCancel];
? ???[request?release];
? ???...
? ???[super?dealloc];
? }
?
向服務器端上傳數據
?
????ASIFormDataRequest?,模擬?Form?表單提交,其提交格式與?Header?會自動識別。
?
沒有文件:application/x-www-form-urlencoded
有文件:multipart/form-data
? 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"];
? ????[request?addData:imageData?withFileName:@"george.jpg"?andContentType:@"image/jpeg"?forKey:@"photos"];
?
如果要發送自定義數據:
? 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"];
?
下載文件
?
????通過設置request的setDownloadDestinationPath,可以設置下載文件用的下載目標目錄。
?
????首先,下載過程文件會保存在temporaryFileDownloadPath目錄下。如果下載完成會做以下事情:
?
如果數據是壓縮的,進行解壓,并把文件放在?downloadDestinationPath?目錄中,臨時文件被刪除
如果下載失敗,臨時文件被直接移到?downloadDestinationPath?目錄,并替換同名文件
????如果你想獲取下載中的所有數據,可以實現?delegate?中的?request:didReceiveData:方法。但如果你實現了這個方法,request?在下載完后,request?并不把文件放在?downloadDestinationPath?中,需要手工處理。
?
獲取響應信息
?
????信息:status?,?header,?responseEncoding
?
????[request?responseStatusCode];
????[[request?responseHeaders]?objectForKey:@"X-Powered-By"];
????[request?responseEncoding];
?
獲取請求進度
?
?
?
????有兩個回調方法可以獲取請求進度:
?
downloadProgressDelegate,可以獲取下載進度
uploadProgressDelegate,可以獲取上傳進度
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]);
?
大文件斷點續傳
?
????0.94?以后支持大文件的斷點下載,只需要設置
? [?request?setAllowResumeForFileDownloads:YES?];
?
? [?request?setDownloadDestinationPath:downloadPath?];
?
就可以了。
?
ASIHTTPRequest會自動保存訪問過的URL信息,并備之后用。在以下幾個場景非常有用:
1,當沒有網絡連接的時候。
2,已下載的數據再次請求時,僅當它與本地版本不樣時才進行下載。
ASIDownloadCache?設置下載緩存
它對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]];
緩存策略
緩存策略是我們控制緩存行為的主要方式,如:什么時候進行緩存,緩存數據的利用方式。
以下是策略可選列表(可組合使用):
ASIUseDefaultCachePolicy
這是一個默認的緩存策略“ASIAskServerIfModifiedWhenStaleCachePolicy”,這個很明白,見名知意(它不能與其它策略組合使用)
ASIDoNotReadFromCacheCachePolicy
所讀數據不使用緩存
ASIDoNotWriteToCacheCachePolicy
不對緩存數據進行寫操作
ASIAskServerIfModifiedWhenStaleCachePolicy
默認緩存行為,request會先判斷是否存在緩存數據。a,?如果沒有再進行網絡請求。?b,如果存在緩存數據,并且數據沒有過期,則使用緩存。c,如果存在緩存數據,但已經過期,request會先進行網絡請求,判斷服務器版本與本地版本是否一樣,如果一樣,則使用緩存。如果服務器有新版本,會進行網絡請求,并更新本地緩存
ASIAskServerIfModifiedCachePolicy
與默認緩存大致一樣,區別僅是每次請求都會?去服務器判斷是否有更新
ASIOnlyLoadIfNotCachedCachePolicy
如果有緩存在本地,不管其過期與否,總會拿來使用
ASIDontLoadCachePolicy
僅當有緩存的時候才會被正確執行,如果沒有緩存,request將被取消(沒有錯誤信息)
ASIFallbackToCacheIfLoadFailsCachePolicy
這個選項經常被用來與其它選項組合使用。請求失敗時,如果有緩存當網絡則返回本地緩存信息(這個在處理異常時非常有用)
?
如果設置了“defaultCachePolicy”則所有的請求都會使用此緩存。
緩存存儲方式
你可以設置緩存的數據需要保存多長時間,ASIHTTPRequest提供了兩種策略:
a,ASICacheForSessionDurationCacheStoragePolicy,默認策略,基于session的緩存數據存儲。當下次運行或[ASIHTTPRequest?clearSession]時,緩存將失效。
b,ASICachePermanentlyCacheStoragePolicy,把緩存數據永久保存在本地,
如:
ASIHTTPRequest?*request?=?[?ASIHTTPRequest?requestWithURL:url?];
[?request?setCacheStoragePolicy:ASICachePermanentlyCacheStoragePolicy?];
另外,也可以使用clearCachedResponsesForStoragePolicy來清空指定策略下的緩存數據。
緩存其它特性
設置是否按服務器在Header里指定的是否可被緩存或過期策略進行緩存:
[[?ASIDownloadCache?sharedCache?]?setShouldRespectCacheControlHeaders:NO?];
設置request緩存的有效時間:
[?request?setSecondsToCache:60*60*24*30?];?//?緩存30天
可以判斷數據是否從緩存讀取:
[?request?didUseCachedResponse?];
設置緩存所使用的路徑:
//[?request?setDownloadDestinationPath:[[?ASIDownloadCache?sharedCache?]?pathToStoreCachedResponseDataForRequest:request?]];
?
[?request?setDownloadDestinationPath:
[[?ASIDownloadCache?sharedCache?]?pathToStoreCachedResponseDataForRequest:request?]];
實現自定義的緩存
只要簡單的實現ASICacheDelegate接口就可以被用來使用。
使用代理請求
默認的情況下,ASIHTTPRequest會使用被設置的默認代理。但你也可以手動修改http代理:
//?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"]];
?
[request?setPACurl:?[NSURL?URLWithString:@"file:///Users/ben/Desktop/test.pac"]];
ASIHTTPRequest,?請求的其它特性
iOS4中,當應用后臺運行時仍然請求數據:
[?request?setShouldContinueWhenAppEntersBackground:YES?];
是否有網絡請求:
[?ASIHTTPRequest?isNetworkInUse?]
是否顯示網絡請求信息在status?bar上:
[?ASIHTTPRequest?setShouldUpdateNetworkActivityIndicator:NO?];
設置請求超時時,設置重試的次數:
[?request?setNumberOfTimesToRetryOnTimeout:2?];
KeepAlive的支持:
//?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?];
版權歸旺財勇士所有~轉載需聲名~
?
??下面來兩個ASIHTTPRequest的小例子:
NSURL?*url?=?[NSURL?URLWithString:@"http://www.baidu.com"];
ASIHTTPRequest?*request?=?[ASIHTTPRequest?requestWithURL:url];
[request?start];
NSError?*error?=?[request?error];
if?(!error)?{
????NSString?*response?=?[request?responseString];
}
??當你需要添加更多的請求信息時,如,添加個請求Header:
[request?addRequestHeader:@"name"?value:@"Jory?lee"];
??添加Post請求時的健值:
[request?setPostValue:@"Ben"?forKey:@"first_name"];
[request?setPostValue:@"Copsey"?forKey:@"last_name"];
[request?setFile:@"/Users/ben/Desktop/ben.jpg"?forKey:@"photo"];
??設置HTTP的授權帳號:
[request?setUsername:@"username"];
[request?setPassword:@"password"];
??一個異步請求:
-?(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];
}??
??在我們數據獲取的過程中,如果數據源復雜,一個請求隊列是必不可少的:
-?(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
}
-?(void)requestDone:(ASIHTTPRequest?*)request
{
NSString?*response?=?[request?responseString];
}
-?(void)requestWentWrong:(ASIHTTPRequest?*)request
{
NSError?*error?=?[request?error];
}??
??另外大家可以通過下面這個代碼例子,看?ASIHTTP?比傳統的?post?方法的方便之處post用法
????NSString?*post?=?@"這里放要傳遞的參數";???
????NSData?*postData?=?[post?dataUsingEncoding:NSASCIIStringEncoding?allowLossyConversion:YES];???
????
????NSString?*postLength?=?[NSString?stringWithFormat:@"%d",?[postData?length]];???
????
????NSMutableURLRequest?*request?=?[[[NSMutableURLRequest?alloc]?init]?autorelease];???
????[request?setURL:[NSURL?URLWithString:@"請求地址"]];???
????[request?setHTTPMethod:@"POST"];???
????[request?setValue:postLength?forHTTPHeaderField:@"Content-Length"];?
????//[request?addValue:@"gzip"?forHTTPHeaderField:@"Accepts-Encoding"];
????[request?setValue:@"application/x-www-form-urlencoded"?forHTTPHeaderField:@"Content-Type"];???
????[request?setHTTPBody:postData];???
????NSURLConnection?*conn=[[NSURLConnection?alloc]?initWithRequest:request?delegate:self];??
????
????if?(conn)????
????{???
????????receivedbData?=?[[NSMutableData?data]?retain];???
????}????
????else????
????{???
????????//?inform?the?user?that?the?download?could?not?be?made???
????}?
ASIHTTP?方法
NSURL?*url?=?[NSURL?URLWithString:@"請求地址"];
//ASIHTTPRequest?*request?=?[ASIHTTPRequest?requestWithURL:url];
ASIFormDataRequest?*request=[ASIFormDataRequest?requestWithURL:url];
[request?setPostValue:@"值"?forKey:@"參數1"];
[request?setPostValue:@"值"?forKey:@"參數2"];
[request?start];
NSError?*error?=?[request?error];
if?(!error)?{
NSString?*response?=?[request?responseString];
NSLog(response);
}
相比之下,ASIHTTP?的確省了很多代碼。更多信息請訪問官方網站?http://allseeing-i.com/
以上內容均來自互聯網,本人不對其準確性和版權糾紛負責。
轉載于:https://www.cnblogs.com/Camier-myNiuer/p/3721269.html
總結
以上是生活随笔為你收集整理的ASIHTTP 框架,同步、 异步请求、 上传 、 下载的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Dynamics AX 2012 R2
- 下一篇: 一道数组求连续子集最大值的题目。