平時(shí)在項(xiàng)目中一直是用網(wǎng)絡(luò)請(qǐng)求的第三方框架 AFNetwork和 ASIHTTPRequest比較多一些肩狂。最近還是想系統(tǒng)的從蘋果官方的原生網(wǎng)絡(luò)類開始做一個(gè)詳細(xì)的了解。
原生網(wǎng)絡(luò)請(qǐng)求類
首先蘋果官方提供的原生網(wǎng)絡(luò)請(qǐng)求類包括:NSURLConnection和NSURLSession荔仁。
其中,NSURLConnection從iOS9開始不被官方推薦使用了,而推薦使用從iOS7開始出現(xiàn)的NSURLSession慎璧。
我們通過提供 NSURLRequest對(duì)象給NSURLConnection哄孤,來異步的加載URL的內(nèi)容。
NSURLConnection的接口比較少吹截,只提供了開始和取消URL請(qǐng)求的操作瘦陈。
NSURLRequest不能修改請(qǐng)求方式凝危,默認(rèn)GET請(qǐng)求;
NSMutableURLRequest可以修改請(qǐng)求方式晨逝。
NSURLConnection請(qǐng)求的方式有三種:
NSURLConnection的類目 NSURLConnectionSynchronousLoading提供了同步加載的方法:
+ (nullable NSData *)sendSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse * _Nullable * _Nullable)response error:(NSError **)error API_DEPRECATED("Use [NSURLSession dataTaskWithRequest:completionHandler:] (see NSURLSession.h", macos(10.3,10.11), ios(2.0,9.0), tvos(9.0,9.0)) __WATCHOS_PROHIBITED;
NSURLConnection的類目 NSURLConnectionQueuedLoading提供了異步加載的方法:
+ (void)sendAsynchronousRequest:(NSURLRequest*) request
? ? ? ? ? ? ? ? ? ? ? ? ? queue:(NSOperationQueue*) queue
? ? ? ? ? ? ? completionHandler:(void (^)(NSURLResponse* _Nullable response, NSData* _Nullable data, NSError* _Nullable connectionError)) handler API_DEPRECATED("Use [NSURLSession dataTaskWithRequest:completionHandler:] (see NSURLSession.h", macos(10.7,10.11), ios(5.0,9.0), tvos(9.0,9.0)) __WATCHOS_PROHIBITED;
邏輯上來講支鸡,NSURLConnectionDownloadDelegate,NSURLConnectionDataDelegate趁窃,都是NSURLConnectionDelegate的子類牧挣。
我們可以通過遵守NSURLConnectionDelegate,NSURLConnectionDownloadDelegate醒陆,NSURLConnectionDataDelegate協(xié)議的代理對(duì)象來創(chuàng)建URLconnection對(duì)象瀑构。
當(dāng)URL請(qǐng)求加載時(shí),這些connection會(huì)調(diào)用代理的方法來提供加載進(jìn)度和狀態(tài)刨摩。也可以調(diào)用代理方法來復(fù)寫這些connection的默認(rèn)行為(比如寺晌,指定如何處理特定的重定向)。
當(dāng)加載失敗時(shí)澡刹,調(diào)用NSURLConnectionDelegate的代理方法:
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error;
當(dāng)加載完成并加載成功時(shí)呻征,調(diào)用NSURLConnectionDelegate的代理方法:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection;
和NSURLConnectionDownloadDelegate的代理方法:
//加載成功后提供下載文件的位置
- (void)connectionDidFinishDownloading:(NSURLConnection *)connection destinationURL:(NSURL *) destinationURL;
//發(fā)送同步請(qǐng)求像屋,會(huì)阻塞主線程
NSURL *url = [NSURL URLWithString:@"https://www.baidu.com/"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSHTTPURLResponse *response = nil;
NSError *error = nil;
NSData *syncData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
NSString *str = [[NSString alloc] initWithData:syncData encoding:NSUTF8StringEncoding];
NSLog(@"syncData = %@", str);
//發(fā)送異步請(qǐng)求
NSURL *url = [NSURL URLWithString:@"https://www.baidu.com/"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc]init] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
? ? NSString *str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
? ? NSLog(@"AsyncData = %@", str);
}];
創(chuàng)建請(qǐng)求己莺,并設(shè)置代理
- (void)pressbtn1
{
? ? NSURL *url = [NSURL URLWithString: @"https://www.baidu.com/"];
? ? NSURLRequest *request = [NSURLRequest requestWithURL:url];
? ? _connect = [NSURLConnection connectionWithRequest:request delegate:self];
}
代理方法
#pragma mark -NSURLConnectionDataDelegate
//接收到服務(wù)器響應(yīng)時(shí)調(diào)用
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
? ? //將響應(yīng)碼轉(zhuǎn)化成為HHTTP響應(yīng)碼
? ? NSHTTPURLResponse *res = (NSHTTPURLResponse *)response;
? ? if(res.statusCode == 200)
? ? {
? ? ? ? NSLog(@"請(qǐng)求成功");
? ? }
? ? else if (res.statusCode == 404)
? ? {
? ? ? ? NSLog(@"沒有找到文件");
? ? }
? ? else if(res.statusCode == 500)
? ? {
? ? ? ? NSLog(@"服務(wù)器內(nèi)部錯(cuò)誤");
? ? }
}
//當(dāng)接收到數(shù)據(jù)時(shí)調(diào)用
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
? ? [_data appendData:data];
}
//當(dāng)服務(wù)器數(shù)據(jù)返回完畢時(shí)調(diào)用
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
? ? NSString *str = [[NSString alloc] initWithData:_data encoding:NSUTF8StringEncoding];
? ? NSLog(@"代理 data = %@", str);
}
NSURLSession類及其相關(guān)類提供了下載內(nèi)容的API和很多代理方法,如支持認(rèn)證凌受,斷點(diǎn)續(xù)傳阵子,當(dāng)APP沒有運(yùn)行或者被掛起時(shí),后臺(tái)下載的功能胜蛉。
NSURLSession支持HTTP/1.1挠进,SPDY,HTTP/2協(xié)議誊册。
使用NSURLSession的API领突,我們可以創(chuàng)建一個(gè)或多個(gè)會(huì)話,每個(gè)會(huì)話都協(xié)調(diào)管理一組相關(guān)的數(shù)據(jù)傳輸任務(wù)案怯。
舉個(gè)例子君旦,在一個(gè)web瀏覽器中,我們可以為每個(gè)標(biāo)簽或窗口創(chuàng)建一個(gè)會(huì)話,可以為交互使用創(chuàng)建一個(gè)會(huì)話金砍,也可以為后臺(tái)下載創(chuàng)建另一個(gè)會(huì)話局蚀。
在每個(gè)會(huì)話里,APP可以添加一系列任務(wù)恕稠,每個(gè)任務(wù)都代表一個(gè)特定URL的請(qǐng)求琅绅。
在一個(gè)給定的URL會(huì)話中,所有的任務(wù)共享一個(gè)會(huì)話配置對(duì)象 NSURLSessionConfiguration鹅巍,它定義了連接的配置方式千扶,比如同時(shí)連接到單個(gè)主機(jī)的最大數(shù),是否允許通過蜂窩網(wǎng)連接等等昆著。
會(huì)話的方式取決于創(chuàng)建它的配置對(duì)象:
1县貌、單例會(huì)話。單例共享的會(huì)話用于基本請(qǐng)求凑懂,沒有配置對(duì)象。這種會(huì)話不可定制梧宫,但是如果要求不多的話接谨,可以選擇這種方式。我們可以通過調(diào)用sharedSession的類方法來訪問該會(huì)話塘匣。
2脓豪、默認(rèn)會(huì)話。默認(rèn)會(huì)話和單例會(huì)話非常相似忌卤,但是我們可以使用代理獲取更多的數(shù)據(jù)扫夜。我們可以調(diào)用NSURLSessionConfiguration類中的defaultSessionConfiguration方法創(chuàng)建默認(rèn)的會(huì)話配置。
3驰徊、短會(huì)話笤闯。短會(huì)話和默認(rèn)會(huì)話很相似,但是不會(huì)將cache棍厂,cookies或credential寫入磁盤颗味。可以通過調(diào)用NSURLSessionConfiguration類中的ephemeralSessionConfiguration方法創(chuàng)建短會(huì)話配置牺弹。
4浦马、后臺(tái)會(huì)話。后臺(tái)會(huì)話可以在APP沒有運(yùn)行時(shí)在后臺(tái)上傳或者下載张漂【可以通過調(diào)用NSURLSessionConfiguration類中的backgroundSessionConfiguration方法創(chuàng)建后臺(tái)會(huì)話配置。
會(huì)話配置對(duì)象也包含了對(duì) URLCache和 HTTPCookieStorage對(duì)象的引用航攒,在做請(qǐng)求磺陡、處理響應(yīng)和決定配置和請(qǐng)求類型時(shí)使用。
會(huì)話中的任務(wù)也會(huì)共享一個(gè)通用代理,使我們?cè)诟鞣N事件發(fā)生時(shí)(比如認(rèn)證失敗時(shí)仅政,數(shù)據(jù)從服務(wù)器到達(dá)時(shí)垢油,數(shù)據(jù)準(zhǔn)備好被緩存時(shí)等等),提供或獲取信息圆丹。使用URL會(huì)話滩愁,當(dāng)會(huì)話在執(zhí)行任務(wù)時(shí),會(huì)有一個(gè)事件逐步發(fā)生的列表辫封,從而相應(yīng)的代理方法會(huì)被調(diào)用硝枉。
另一方面,如果不需要代理提供的任何功能倦微,我們也可以在創(chuàng)建會(huì)話時(shí)妻味,通過傳遞nil來使用這個(gè)API,不提供任何功能欣福。
注意:
會(huì)話對(duì)象保持著代理的強(qiáng)引用直到APP運(yùn)行或會(huì)話明確無效责球。如果不廢除這個(gè)會(huì)話,APP就會(huì)內(nèi)存泄漏拓劝。
在會(huì)話中雏逾,我們可以創(chuàng)建上傳數(shù)據(jù)到服務(wù)器的任務(wù),也可以創(chuàng)建任務(wù)從服務(wù)器獲取數(shù)據(jù)來作為磁盤文件或內(nèi)存NSData對(duì)象郑临。
NSURLSession的API提供了3種類型的任務(wù):
1栖博、Data任務(wù)。Data任務(wù)使用NSData對(duì)象發(fā)送或接收數(shù)據(jù)厢洞。Data任務(wù)旨在對(duì)服務(wù)器短而頻繁的交互請(qǐng)求仇让。
2、 Upload任務(wù)躺翻。上傳任務(wù)和Data任務(wù)相似丧叽,但是它也可以發(fā)送數(shù)據(jù)(通常是文件形式),當(dāng)APP不運(yùn)行時(shí)获枝,支持后臺(tái)上傳蠢正。
3、 Download任務(wù)省店。下載任務(wù)以文件形式獲取數(shù)據(jù)嚣崭,當(dāng)APP不運(yùn)行時(shí),支持后臺(tái)下載懦傍。
和大部分網(wǎng)絡(luò)API一樣雹舀,NSURLSession的API是高度異步的。它會(huì)以下面兩種方式中的一種來返回?cái)?shù)據(jù)粗俱,取決于你調(diào)用的方法:
1说榆、當(dāng)傳輸成功完成或者傳輸錯(cuò)誤時(shí),調(diào)用完成處理的block;
2签财、當(dāng)接收到數(shù)據(jù)或傳輸完成時(shí)串慰,調(diào)用session的代理。
NSURLSession的API還提供了查詢狀態(tài)和進(jìn)度的屬性唱蒸,可以跟筠需要對(duì)任務(wù)當(dāng)前的狀態(tài)(隨時(shí)注意狀態(tài)變化)來做一些項(xiàng)目決策邦鲫。
URL會(huì)話也支持取消,重新開始神汹,繼續(xù)庆捺,掛起任務(wù),并支持繼續(xù)下載掛起屁魏、下載取消滔以、下載失敗的功能。
使用NSURLSession類請(qǐng)求:
1氓拼、創(chuàng)建一個(gè)session配置你画。對(duì)于后臺(tái)會(huì)話,這個(gè)配置必須包含唯一標(biāo)識(shí)符桃漾。存儲(chǔ)標(biāo)識(shí)符撬即,當(dāng)APP崩掉或結(jié)束掛起時(shí),使用它來重連會(huì)話呈队。
2、創(chuàng)建會(huì)話唱歧,指定配置對(duì)象和代理宪摧。
3、在會(huì)話中創(chuàng)建任務(wù)對(duì)象颅崩,每個(gè)任務(wù)代表一個(gè)URL請(qǐng)求几于。
這些任務(wù)對(duì)象是NSURLSessionTask——NSURLSessionDataTask, NSURLSessionUploadTask, NSURLSessionDownloadTask,取決于你創(chuàng)建的方式沿后。
每個(gè)任務(wù)的初始狀態(tài)都是都是暫停狀態(tài)沿彭。APP在任務(wù)中調(diào)用resume方法后,就開始下載指定資源尖滚。
開始任務(wù)后喉刘,會(huì)話調(diào)用代理方法的步驟:
1、如果與服務(wù)器第一次握手需要連接的身份認(rèn)證(如SSL客戶端認(rèn)證)漆弄,NSURLSession會(huì)調(diào)用代理方法
URLSession:task:didReceiveChallenge:completionHandler:
或
URLSession:didReceiveChallenge:completionHandler:
2睦裳、如果任務(wù)的數(shù)據(jù)從流中獲取,NSURLSession調(diào)用代理方法
URLSession:task:needNewBodyStream:
來獲取NSInputStream的實(shí)例為新的請(qǐng)求提供body數(shù)據(jù)撼唾。
3廉邑、在body內(nèi)容第一次上傳到服務(wù)器期間,代理定期會(huì)收到回調(diào)
URLSession:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:
來報(bào)告上傳的進(jìn)度。
4蛛蒙、服務(wù)器發(fā)送響應(yīng)糙箍。
5、如果響應(yīng)指明要求認(rèn)證牵祟,會(huì)話調(diào)用代理的
URLSession:task:didReceiveChallenge:completionHandler:
方法深夯。回到第2步课舍。
6塌西、如果響應(yīng)是HTTP重定向響應(yīng)藕坯,NSURLSession對(duì)象調(diào)用代理的方法
URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler:
代理方法使用所提供的NSURLRequest對(duì)象(遵循重定向)肺缕,一個(gè)新的NSURLRequest對(duì)象(重定向到不同URL)柒爸,或者nil(將重定向的響應(yīng)體作為有效響應(yīng)并作為結(jié)果返回)來調(diào)用所提供的completion處理回調(diào)废赞。
如果要遵循重定向瞳浦,回到第2步喷斋。
如果代理沒有實(shí)現(xiàn)這個(gè)方法培漏,重定向追蹤最大重定向數(shù)兑巾。
7损姜、對(duì)于通過調(diào)用
downloadTaskWithResumeData:
或
downloadTaskWithResumeData:completionHandler:
創(chuàng)建的下載(或重下載)任務(wù)饰剥,NSURLSession使用新任務(wù)對(duì)象調(diào)用代理方法
URLSession:downloadTask:didResumeAtOffset:expectedTotalBytes:
8、對(duì)于數(shù)據(jù)任務(wù)摧阅,NSURLSession對(duì)象調(diào)用代理方法
URLSession:dataTask:didBecomeDownloadTask:
汰蓉,來決定是否轉(zhuǎn)變數(shù)據(jù)任務(wù)為下載任務(wù),然后調(diào)用處理回調(diào)來轉(zhuǎn)變棒卷,繼續(xù)顾孽,取消任務(wù)。如果APP選擇將數(shù)據(jù)任務(wù)轉(zhuǎn)變?yōu)橄螺d任務(wù)比规,NSURLSession會(huì)使用新下載任務(wù)作為參數(shù)調(diào)用代理的方法若厚。調(diào)用之后,代理不會(huì)收到來自數(shù)據(jù)任務(wù)的進(jìn)一步回調(diào)蜒什,而是開始收到來自下載任務(wù)的回調(diào)测秸。
9、在從服務(wù)器傳輸?shù)倪^程中灾常,代理會(huì)定時(shí)的收到任務(wù)的回調(diào)來報(bào)告?zhèn)鬏數(shù)倪M(jìn)度霎冯。
對(duì)于數(shù)據(jù)任務(wù),會(huì)話使用他們收到的原始數(shù)據(jù)調(diào)用代理的方法
URLSession:dataTask:didReceiveData:
對(duì)于下載任務(wù)岗憋,會(huì)話使用成功寫入磁盤的字節(jié)數(shù)調(diào)用代理的方法
URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:
如果用戶告訴APP暫停下載肃晚,通過調(diào)用
cancelByProducingResumeData:
方法取消任務(wù)。
最后仔戈,如果用戶告訴APP繼續(xù)下載关串,那么需要傳遞已經(jīng)返回的resume數(shù)據(jù)給
downloadTaskWithResumeData:
方法或
downloadTaskWithResumeData:completionHandler:
方法來創(chuàng)建新的下載任務(wù)來繼續(xù)下載拧廊。(回到第1步)。
10晋修、對(duì)于數(shù)據(jù)任務(wù)吧碾,NSURLSession對(duì)象可調(diào)用
URLSession:dataTask:willCacheResponse:completionHandler:
方法。然后APP決定是否允許緩存墓卦。如果你沒有實(shí)現(xiàn)這個(gè)方法倦春,默認(rèn)的方式是使用會(huì)話的配置對(duì)象中指定的緩存策略。
11落剪、如果響應(yīng)是多部分編碼的睁本,會(huì)話可再次調(diào)用代理的didReceiveResponse方法,然后不調(diào)用或者多次調(diào)用didReceiveData忠怖。如果這樣的情況發(fā)生了呢堰,那么請(qǐng)轉(zhuǎn)至步驟8(處理didReceiveResponse調(diào)用)。
12凡泣、如果下載任務(wù)成功完成枉疼,那么NSURLSession對(duì)象使用臨時(shí)文件的位置調(diào)用任務(wù)的
URLSession:downloadTask:didFinishDownloadingToURL:
方法。APP必須在代理方法返回前鞋拟,要么從這個(gè)文件中讀取響應(yīng)數(shù)據(jù)骂维,要么把它移動(dòng)到持久存儲(chǔ)的位置。
13贺纲、當(dāng)任務(wù)完成時(shí)航闺,NSURLSession對(duì)象使用一個(gè)error對(duì)象或者nil(如果任務(wù)成功完成)調(diào)用代理的方法
URLSession:task:didCompleteWithError:
如果下載任務(wù)繼續(xù),NSError對(duì)象的userInfo字典包含了NSURLSessionDownloadTaskResumeData 鍵的值猴誊。APP傳遞這個(gè)值來調(diào)用方法
downloadTaskWithResumeData:
或方法
downloadTaskWithResumeData:completionHandler:
來創(chuàng)建新的下載任務(wù)來繼續(xù)存在的下載来颤。
如果任務(wù)沒有被繼續(xù),APP就會(huì)創(chuàng)建一個(gè)新的下載任務(wù)并從開始重啟事件稠肘。
這兩種情況下,如果傳輸失敗萝毛,如果不是服務(wù)器原因项阴,請(qǐng)轉(zhuǎn)至步驟3(創(chuàng)建和繼續(xù)任務(wù))。
14笆包、如果不再需要會(huì)話环揽,我們可以通過調(diào)用invalidateAndCancel(取消任務(wù))或finishTasksAndInvalidate (允許任務(wù)來在廢棄之前完成)。
如果沒有廢棄會(huì)話庵佣,當(dāng)APP終止時(shí)歉胶,它會(huì)自動(dòng)消失(除非是具有活動(dòng)任務(wù)的后臺(tái)會(huì)話)。
在廢棄會(huì)話后巴粪,當(dāng)所有的任務(wù)被取消或完成時(shí)通今,會(huì)話會(huì)調(diào)用代理的URLSession:didBecomeInvalidWithError:方法粥谬。
當(dāng)代理方法返回時(shí),會(huì)話釋放代理的強(qiáng)引用辫塌。
如果APP取消了正在進(jìn)行的下載漏策,雖然會(huì)發(fā)生錯(cuò)誤,NSURLSession對(duì)象還是會(huì)調(diào)用代理的 URLSession:task:didCompleteWithError:方法臼氨。
URL會(huì)話的API都是完全線程安全的掺喻。可任意創(chuàng)建會(huì)話和任務(wù)储矩。代理方法調(diào)用完成處理回調(diào)時(shí)感耙,會(huì)在代理隊(duì)列中被自動(dòng)適當(dāng)安排。
會(huì)話和任務(wù)都遵守NSCopying協(xié)議持隧,當(dāng)copy一個(gè)會(huì)話或者任務(wù)時(shí)即硼,我們會(huì)得到一個(gè)相同對(duì)象。而當(dāng)copy一個(gè)配置對(duì)象時(shí)舆蝴,我們會(huì)得到一個(gè)新的對(duì)象谦絮,可以獨(dú)立的修改。
App Transport Security (ATS)應(yīng)用傳輸安全
在iOS9.0和 OS X10.11開始出現(xiàn)洁仗,對(duì)于使用NSURLSession的所有HTTP連接层皱,默認(rèn)會(huì)啟用這個(gè)叫做ATS的新安全功能。ATS要求HTTP連接使用HTTPS(RFC 2818)赠潦。
不同會(huì)話方式和不同任務(wù)類型的請(qǐng)求示例
使用Block來處理請(qǐng)求
(1)、Data任務(wù)
//1她奥、創(chuàng)建單例會(huì)話
NSURLSession *session = [NSURLSession sharedSession];
//2瓮增、創(chuàng)建請(qǐng)求和任務(wù)對(duì)象
NSURL *url = [NSURL URLWithString:@"http://www.reibang.com/u/8ca9e2a2536a"];
NSURLSessionDataTask *dataTask = [session dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError *error){
? ? if (error == nil && data)
? ? {
? ? ? ? NSString *dataStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
? ? ? ? NSLog(@"請(qǐng)求成功 = %@", dataStr);
? ? }
? ? else
? ? {
? ? ? ? NSLog(@"請(qǐng)求失敗");
? ? }
}];
[dataTask resume];
//1哩俭、創(chuàng)建單例會(huì)話
NSURLSession *session = [NSURLSession sharedSession];
//2绷跑、創(chuàng)建請(qǐng)求和任務(wù)對(duì)象
NSURL *url = [NSURL URLWithString:@"https://image.baidu.com/search/detail?ct=503316480&z=0&ipn=d&word=%E5%9B%BE%E7%89%87&hs=0&pn=0&spn=0&di=113313207810&pi=0&rn=1&tn=baiduimagedetail&is=0%2C0&ie=utf-8&oe=utf-8&cl=2&lm=-1&cs=594559231%2C2167829292&os=2394225117%2C7942915&simid=3436308227%2C304878115&adpicid=0&lpn=0&ln=30&fr=ala&fm=&sme=&cg=&bdtype=0&oriquery=&objurl=http%3A%2F%2Fimg.taopic.com%2Fuploads%2Fallimg%2F120727%2F201995-120HG1030762.jpg&fromurl=ippr_z2C%24qAzdH3FAzdH3Fooo_z%26e3Bpw5rtv_z%26e3Bv54AzdH3Fejvp56AzdH3Fda8da0AzdH3Fdanll9_z%26e3Bip4s&gsm=0&islist=&querylist="];
NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithURL:url completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error){
? ? if (error == nil && location)
? ? {
? ? ? ? NSLog(@"下載成功:location.path = %@", location.path);
? ? ? ? NSString *filePath = @"/Users/shiru/Desktop/downloadImage.png";
? ? ? ? NSError *fileError;
? ? ? ? [[NSFileManager defaultManager] copyItemAtPath:location.path toPath:filePath error:&fileError];
? ? ? ? if (fileError == nil) {
? ? ? ? ? ? NSLog(@"file save success");
? ? ? ? } else {
? ? ? ? ? ? NSLog(@"file save error: %@",fileError);
? ? ? ? }
? ? }
? ? else
? ? {
? ? ? ? NSLog(@"下載失敗error");
? ? }
}];
[downloadTask resume];
//1凡资、創(chuàng)建單例會(huì)話
NSURLSession *session = [NSURLSession sharedSession];
//2砸捏、創(chuàng)建請(qǐng)求和任務(wù)對(duì)象
NSURL *url = [NSURL URLWithString:@"https://www.freeimagehosting.net/upl.php"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST";
NSData *data = [NSData dataWithContentsOfFile:@"/Users/shiru/Desktop/private/個(gè)人相關(guān)/天籟小學(xué).jpg"];
NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request fromData:data completionHandler:^(NSData *data, NSURLResponse *response, NSError *error){
? ? if (error == nil && data)
? ? {
? ? ? ? NSString *dataStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
? ? ? ? NSLog(@"上傳成功:dataStr = %@", dataStr);
? ? }
? ? else
? ? {
? ? ? ? NSLog(@"上傳失敗");
? ? }
}];
[uploadTask resume];
####(1)隙赁、Data任務(wù)
在這里使用NSURLSessionDataDelegate代理的方法來處理請(qǐng)求
{
? ? //1垦藏、創(chuàng)建會(huì)話配置
? ? NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
? ? configuration.allowsCellularAccess = NO;
? ? configuration.timeoutIntervalForRequest = 10;
? ? //2、創(chuàng)建單例會(huì)話
? ? NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:[NSOperationQueue mainQueue]];
? ? //3伞访、創(chuàng)建請(qǐng)求和任務(wù)對(duì)象
? ? NSURL *url = [NSURL URLWithString:@"http://www.reibang.com/u/8ca9e2a2536a"];
? ? NSURLSessionDataTask *dataTask = [session dataTaskWithURL:url];
? ? [dataTask resume];
}
#pragma mark -NSURLSessionDataDelegate
//接收到服務(wù)器響應(yīng)
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
didReceiveResponse:(NSURLResponse *)response
completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler
{
? ? completionHandler(NSURLSessionResponseAllow);// 允許處理服務(wù)器的響應(yīng)掂骏,才會(huì)繼續(xù)接收服務(wù)器返回的數(shù)據(jù)
}
//接收服務(wù)器回傳的數(shù)據(jù),有可能執(zhí)行多次
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
? ? didReceiveData:(NSData *)data
{
? ? if (data)
? ? {
? ? ? ? NSString *dataStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
? ? ? ? NSLog(@"請(qǐng)求成功 = %@", dataStr);
? ? }
? ? else
? ? {
? ? ? ? NSLog(@"請(qǐng)求失敗");
? ? }
}
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
willCacheResponse:(NSCachedURLResponse *)proposedResponse
completionHandler:(void (^)(NSCachedURLResponse * _Nullable cachedResponse))completionHandler
{
}
{
? ? //1厚掷、創(chuàng)建會(huì)話配置
? ? NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
? ? configuration.allowsCellularAccess = NO;
? ? configuration.timeoutIntervalForRequest = 10;
? ? //2弟灼、創(chuàng)建單例會(huì)話
? ? NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:[NSOperationQueue mainQueue]];
? ? //3级解、創(chuàng)建請(qǐng)求和任務(wù)對(duì)象
? ? NSURL *url = [NSURL URLWithString:@"http://www.reibang.com/u/8ca9e2a2536a"];
? ? NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithURL:url];
? ? [downloadTask resume];
}
#pragma mark -NSURLSessionDownloadDelegate
//下載完成
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location
{
? ? if (location)
? ? {
? ? ? ? NSLog(@"下載成功:location.path = %@", location.path);
? ? ? ? NSString *filePath = @"/Users/shiru/Desktop/downloadImage1.png";
? ? ? ? NSError *fileError;
? ? ? ? [[NSFileManager defaultManager] copyItemAtPath:location.path toPath:filePath error:&fileError];
? ? ? ? if (fileError == nil) {
? ? ? ? ? ? NSLog(@"file save success");
? ? ? ? } else {
? ? ? ? ? ? NSLog(@"file save error: %@",fileError);
? ? ? ? }
? ? }
? ? else
? ? {
? ? ? ? NSLog(@"下載失敗error");
? ? }
}
/*
監(jiān)測臨時(shí)文件下載的數(shù)據(jù)大小,當(dāng)每次寫入臨時(shí)文件時(shí)袜爪,就會(huì)調(diào)用一次
bytesWritten 每次寫入多少
totalBytesWritten? 已經(jīng)寫入了多少
totalBytesExpectedToWrite 文件總大小
*/
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
? ? ? didWriteData:(int64_t)bytesWritten
totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
? ? //打印下載進(jìn)度
? ? NSLog(@"%f",totalBytesWritten * 1.0 / totalBytesExpectedToWrite);
}
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didResumeAtOffset:(int64_t)fileOffset
expectedTotalBytes:(int64_t)expectedTotalBytes
{
}
//1、創(chuàng)建會(huì)話配置
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
configuration.allowsCellularAccess = NO;
configuration.timeoutIntervalForRequest = 10;
//2辛馆、創(chuàng)建單例會(huì)話
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:[NSOperationQueue mainQueue]];
//3俺陋、創(chuàng)建請(qǐng)求和任務(wù)對(duì)象
NSURL *url = [NSURL URLWithString:@"https://www.freeimagehosting.net/upl.php"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST";
NSData *data = [NSData dataWithContentsOfFile:@"/Users/shiru/Desktop/private/個(gè)人相關(guān)/天籟小學(xué).jpg"];
NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request fromData:data completionHandler:^(NSData *data, NSURLResponse *response, NSError *error){
? ? if (error == nil && data)
? ? {
? ? ? ? NSString *dataStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
? ? ? ? NSLog(@"上傳成功:dataStr = %@", dataStr);
? ? }
? ? else
? ? {
? ? ? ? NSLog(@"上傳失敗");
? ? }
}];
[uploadTask resume];
3、默認(rèn)?會(huì)話實(shí)現(xiàn)斷點(diǎn)續(xù)傳
- (IBAction)startDonload:(id)sender
{
? ? //1昙篙、創(chuàng)建會(huì)話配置
? ? NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
? ? configuration.allowsCellularAccess = NO;
? ? configuration.timeoutIntervalForRequest = 10;
? ? //2腊状、創(chuàng)建單例會(huì)話
? ? NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:[NSOperationQueue mainQueue]];
? ? self.session = session;
? ? //3、創(chuàng)建請(qǐng)求和任務(wù)對(duì)象
? ? NSURL *url = [NSURL URLWithString:@"https://120.25.226.186:32812/resources/videos/minion_02.mp4"];
? ? NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithURL:url];
? ? self.downloadTask = downloadTask;
? ? [self.downloadTask resume];
}
- (IBAction)pauseDownload:(id)sender
{
? ? [self.downloadTask cancelByProducingResumeData:^(NSData *resumeData){
? ? ? ? //將已下載的數(shù)據(jù)保存起來苔可,以備斷點(diǎn)續(xù)傳使用
? ? ? ? self.resumeData = resumeData;
? ? }];
}
- (IBAction)resumeDownload:(id)sender
{
? ? self.downloadTask = [self.session downloadTaskWithResumeData:self.resumeData];
? ? [self.downloadTask resume];
}
#pragma mark -NSURLSessionDownloadDelegate
//下載完成
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location
{
? ? if (location)
? ? {
? ? ? ? NSLog(@"下載成功:location.path = %@", location.path);
? ? ? ? NSString *filePath = @"/Users/shiru/Desktop/downloadMP4File.mp4";
? ? ? ? NSError *fileError;
? ? ? ? [[NSFileManager defaultManager] copyItemAtPath:location.path toPath:filePath error:&fileError];
? ? ? ? if (fileError == nil) {
? ? ? ? ? ? NSLog(@"file save success");
? ? ? ? } else {
? ? ? ? ? ? NSLog(@"file save error: %@",fileError);
? ? ? ? }
? ? }
? ? else
? ? {
? ? ? ? NSLog(@"下載失敗error");
? ? }
}
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
? ? ? didWriteData:(int64_t)bytesWritten
totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
? ? //打印下載百分比
? ? NSLog(@"%f",totalBytesWritten * 1.0 / totalBytesExpectedToWrite);
}