版權歸旺財勇士所有〜轉載需聲名〜
原貼地地址:http://wiki.magiche.net/pages/viewpage.action?pageId=2064410
目錄
ASIHTTPRequest是一款極其強勁的HTTP訪問開源項目。讓簡單的API完成複雜的功能,
如:
異步請求,隊列請求,GZIP壓縮,緩存,斷點續傳,進度跟蹤,上傳文件,HTTP認證
在新的版本中,還加入了Objective-C閉包Block的支持,讓我們的代碼更加輕簡靈活。
下面就舉例說明它的API用法。
發起一個同步請求
同步意爲着線程阻塞,在主線程中使用此方法會使應用Hang住而不響應任何用戶事件。所以,在應用程序設計時,大多被用在專門的子線程增加用戶體驗,或用異步請求代替(下面會講到)。
-
(IBAction)grabURL:(id)sender { ASIHTTPRequest
*request = [ASIHTTPRequest requestWithURL:url]; [request
startSynchronous]; NSError
*error = [request error]; if (!error)
{ NSString
*response = [request responseString]; } } |
a, 用requestWithURL快捷方法獲取ASIHTTPRequest的一個實例
b, startSynchronous 方法啓動同步訪問,
c, 由於是同步請求,沒有基於事件的回調方法,所以從request的error屬性獲取錯誤信息。
d, responseString,爲請求的返回NSString信息。
創建一個異步請求
異步請求的好處是不阻塞當前線程,但相對於同步請求略爲複雜,至少要添加兩個回調方法來獲取異步事件。
下面異步請求代碼完成上面同樣的一件事情:
-
(IBAction)grabURLInBackground:(id)sender { 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]; } |
a,與上面不同的地方是指定了一個 "delegate",並用startAsynchronous來啓動網絡請求。
b,在這裏實現了兩個delegate的方法,當數據請求成功時會調用requestFinished,請求失敗時(如網絡問題或服務器內部錯誤)會調用requestFailed。
隊列請求
提供了一個對異步請求更加精準豐富的控制。
如,可以設置在隊列中,同步請求的連接數。往隊列裏添加的請求實例數大於maxConcurrentOperationCount時,請求實例將被置爲等待,直到前面至少有一個請求完成並出列才被放到隊列裏執行。
也適用於當我們有多個請求需求按順序執行的時候(可能是業務上的需要,也可能是軟件上的調優),僅僅需要把maxConcurrentOperationCount設爲“1”。
-
(IBAction)grabURLInTheBackground:(id)sender { if (![self
queue]) { [self
setQueue:[[[NSOperationQueue alloc] init] autorelease]]; } 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的子類。也就是說它可以直接被放到"任務隊列"中,並被執行。上面的代碼隊了隊列的創建與添加操作外,其它代碼與上一例一樣。
請求隊列上下文
a,可以設置一個上下文(userInfo)到request對象中,當請求響應完後可以通過訪問request對象的userInfo獲取裏面的信息
b,爲每一個請求實例設置不同的setDidFinishSelector / setDidFailSelector的回調方法
c,子類化ASIHTTPRequest,重寫requestFinished: 與 failWithProblem:方法
ASINetworkQueues, 它的delegate提供更爲豐富的功能
提供的更多的回調方法如下:
a,requestDidStartSelector,請求發起時會調此方法,你可以在此方法中跟據業務選擇性的設置request對象的deleaget。
b,requestDidReceiveResponseHeadersSelector,當接受完響應的Header後設計此方法,這個對下載大數據的時候相當有用,你可以在方法裏做更多業務上的處理。
c,requestDidFinishSelector,請求並響應成功完成時調用此方法
d,requestDidFailSelector,請求失敗
e,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目錄下。如果下載完成會做以下事情:
1,如果數據是壓縮的,進行解壓,並把文件放在downloadDestinationPath目錄中,臨時文件被刪除
2,如果下載失敗,臨時文件被直接移到downloadDestinationPath目錄,並替換同名文件。
如果你想獲取下載中的所有數據,可以實現delegate中的request:didReceiveData:方法。但如果你實現了這個方法,request在下載完後,request並不把文件放在downloadDestinationPath中,需要手工處理。
獲取響應信息
信息:status , header, responseEncoding
[request
responseStatusCode]; [[request
responseHeaders] objectForKey:@ "X-Powered-By" ]; [request
responseEncoding]; |
獲取請求進度
有兩個回調方法可以獲取請求進度,
1,downloadProgressDelegate,可以獲取下載進度
2,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 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 ]]; |
實現自定義的緩存
只要簡單的實現ASICacheDelegate接口就可以被用來使用。
使用代理請求
默認的情況下,ASIHTTPRequest會使用被設置的默認代理。但你也可以手動修改http代理:
//
Configure a proxy server manually 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" ]]; |
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,是一個直接在CFNetwork上做的開源項目,提供了一個比官方更方便更強大的HTTP網絡傳輸的封裝。
特色功能如下:
1,下載的數據直接保存到內存或文件系統裏
2,提供直接提交(HTTP POST)文件的API
3,可以直接訪問與修改HTTP請求與響應HEADER
4,輕鬆獲取上傳與下載的進度信息
5,異步請求與隊列,自動管理上傳與下載隊列管理機
6,認證與授權的支持
7,Cookie
8,請求與響應的GZIP
9,代理請求
下面來兩個小例子:
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];
}
1.ASIHTTPRequest:處理與服務器的基本交互,包括下載上傳,認證,cookies以及進度查看。
2.ASIFormDataRequest:是ASIHTTPRequest子類,主要處理post事件,它能使post更加簡單。
3.ASINetworkQueue:是NSOperationQueue子類,當處理多個請求時可以使用,如果每次都是單個請求就不必使用。
4.ASIDownloadCache:該類允許ASIHTTPRequest從服務器傳遞cookie。
ASIHTTPRequest -Support classes介紹:
1.ASIInputStream:當使用ASIHTTPRequest上傳數據時使用,如果工程中用了ASIHTTPRequest,就一定要include這個類。
2.ASIAuthenticationDialog:該類允許ASIHTTPRequest連接到服務器時呈現登錄框。在所有iPhone OS工程中都要使用,Mac OS工程中可以不用。
3.Reachability:相信很多人對這個類已經很熟悉了,當在你程序中偵測網絡狀態時它將非常有用。
ASIHTTPRequest -Protocols and configuration介紹:
1.ASIHTTPRequestDelegate:該協議指定了ASIHTTPRequest的delegate可能需要實現的方法,所有方法都是optional。
2.ASIProgressDelegate:該協議列出了uploadProgressDelegate和downloadProgressDelegate可能需要實現的方法,所有方法爲optional。
3.ASICacheDelegate:該協議指定了download cache必須實現的方法。如果你要寫你自己的download cache,確保實現required方法。
4.ASIHTTPRequestConfig.h:該文件定義了編譯時所有的全局配置選項。使用該文件中的方法可以在控制檯中輸出request正在進行的任務.
如果要在ios中實現類似最簡單的HttpClient應用的功能,可以直接用Cocoa的CFNetwork framework,但是,因爲它是將C語言編寫的BSD網絡庫做的封裝,因此使用起來很繁瑣。
ASIHTTPRequest是第三方HTTP編程的ObjC庫。基於CFNetwork framework。網址在這裏:
要使用該庫,首先是下載部署。下載zip包解壓縮即可。部署可見官方文檔:
這裏也說一下,首先該庫還依賴其他框架和庫:
一般來說,是增加畫紅線的幾個框架。
然後,需要把解壓縮包裏的Classes目錄下全部文件加到項目的Classes下。這裏要注意:
這幾個目錄除外。除非你確實用到它。
另外,還需要加入External/Reachability目錄下的文件。
代碼寫起來很簡單:
-(void) doSimpleGetText{
NSURL *url = [NSURL URLWithString:@"