平時在項目中一直是用網(wǎng)絡請求的第三方框架 AFNetwork和 ASIHTTPRequest比較多一些。最近還是想系統(tǒng)的從蘋果官方的原生網(wǎng)絡類開始做一個詳細的了解。
原生網(wǎng)絡請求類
首先蘋果官方提供的原生網(wǎng)絡請求類包括:NSURLConnection和NSURLSession。
其中,NSURLConnection從iOS9開始不被官方推薦使用了,而推薦使用從iOS7開始出現(xiàn)的NSURLSession。
我們通過提供 NSURLRequest對象給NSURLConnection,來異步的加載URL的內(nèi)容。
NSURLConnection的接口比較少,只提供了開始和取消URL請求的操作。
NSURLRequest不能修改請求方式,默認GET請求;
NSMutableURLRequest可以修改請求方式。
NSURLConnection請求的方式有三種:
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é)議的代理對象來創(chuàng)建URLconnection對象。
當URL請求加載時,這些connection會調(diào)用代理的方法來提供加載進度和狀態(tài)。也可以調(diào)用代理方法來復寫這些connection的默認行為(比如,指定如何處理特定的重定向)。
當加載失敗時,調(diào)用NSURLConnectionDelegate的代理方法:
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error;
當加載完成并加載成功時,調(diào)用NSURLConnectionDelegate的代理方法:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection;
和NSURLConnectionDownloadDelegate的代理方法:
//加載成功后提供下載文件的位置
- (void)connectionDidFinishDownloading:(NSURLConnection *)connection destinationURL:(NSURL *) destinationURL;
//發(fā)送同步請求,會阻塞主線程
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ā)送異步請求
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)建請求,并設置代理
- (void)pressbtn1
{
? ? NSURL *url = [NSURL URLWithString: @"https://www.baidu.com/"];
? ? NSURLRequest *request = [NSURLRequest requestWithURL:url];
? ? _connect = [NSURLConnection connectionWithRequest:request delegate:self];
}
代理方法
#pragma mark -NSURLConnectionDataDelegate
//接收到服務器響應時調(diào)用
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
? ? //將響應碼轉(zhuǎn)化成為HHTTP響應碼
? ? NSHTTPURLResponse *res = (NSHTTPURLResponse *)response;
? ? if(res.statusCode == 200)
? ? {
? ? ? ? NSLog(@"請求成功");
? ? }
? ? else if (res.statusCode == 404)
? ? {
? ? ? ? NSLog(@"沒有找到文件");
? ? }
? ? else if(res.statusCode == 500)
? ? {
? ? ? ? NSLog(@"服務器內(nèi)部錯誤");
? ? }
}
//當接收到數(shù)據(jù)時調(diào)用
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
? ? [_data appendData:data];
}
//當服務器數(shù)據(jù)返回完畢時調(diào)用
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
? ? NSString *str = [[NSString alloc] initWithData:_data encoding:NSUTF8StringEncoding];
? ? NSLog(@"代理 data = %@", str);
}
NSURLSession類及其相關類提供了下載內(nèi)容的API和很多代理方法,如支持認證,斷點續(xù)傳,當APP沒有運行或者被掛起時,后臺下載的功能。
NSURLSession支持HTTP/1.1,SPDY,HTTP/2協(xié)議。
使用NSURLSession的API,我們可以創(chuàng)建一個或多個會話,每個會話都協(xié)調(diào)管理一組相關的數(shù)據(jù)傳輸任務。
舉個例子,在一個web瀏覽器中,我們可以為每個標簽或窗口創(chuàng)建一個會話,可以為交互使用創(chuàng)建一個會話,也可以為后臺下載創(chuàng)建另一個會話。
在每個會話里,APP可以添加一系列任務,每個任務都代表一個特定URL的請求。
在一個給定的URL會話中,所有的任務共享一個會話配置對象 NSURLSessionConfiguration,它定義了連接的配置方式,比如同時連接到單個主機的最大數(shù),是否允許通過蜂窩網(wǎng)連接等等。
會話的方式取決于創(chuàng)建它的配置對象:
1、單例會話。單例共享的會話用于基本請求,沒有配置對象。這種會話不可定制,但是如果要求不多的話,可以選擇這種方式。我們可以通過調(diào)用sharedSession的類方法來訪問該會話。
2、默認會話。默認會話和單例會話非常相似,但是我們可以使用代理獲取更多的數(shù)據(jù)。我們可以調(diào)用NSURLSessionConfiguration類中的defaultSessionConfiguration方法創(chuàng)建默認的會話配置。
3、短會話。短會話和默認會話很相似,但是不會將cache,cookies或credential寫入磁盤。可以通過調(diào)用NSURLSessionConfiguration類中的ephemeralSessionConfiguration方法創(chuàng)建短會話配置。
4、后臺會話。后臺會話可以在APP沒有運行時在后臺上傳或者下載。可以通過調(diào)用NSURLSessionConfiguration類中的backgroundSessionConfiguration方法創(chuàng)建后臺會話配置。
會話配置對象也包含了對 URLCache和 HTTPCookieStorage對象的引用,在做請求、處理響應和決定配置和請求類型時使用。
會話中的任務也會共享一個通用代理,使我們在各種事件發(fā)生時(比如認證失敗時,數(shù)據(jù)從服務器到達時,數(shù)據(jù)準備好被緩存時等等),提供或獲取信息。使用URL會話,當會話在執(zhí)行任務時,會有一個事件逐步發(fā)生的列表,從而相應的代理方法會被調(diào)用。
另一方面,如果不需要代理提供的任何功能,我們也可以在創(chuàng)建會話時,通過傳遞nil來使用這個API,不提供任何功能。
注意:
會話對象保持著代理的強引用直到APP運行或會話明確無效。如果不廢除這個會話,APP就會內(nèi)存泄漏。
在會話中,我們可以創(chuàng)建上傳數(shù)據(jù)到服務器的任務,也可以創(chuàng)建任務從服務器獲取數(shù)據(jù)來作為磁盤文件或內(nèi)存NSData對象。
NSURLSession的API提供了3種類型的任務:
1、Data任務。Data任務使用NSData對象發(fā)送或接收數(shù)據(jù)。Data任務旨在對服務器短而頻繁的交互請求。
2、 Upload任務。上傳任務和Data任務相似,但是它也可以發(fā)送數(shù)據(jù)(通常是文件形式),當APP不運行時,支持后臺上傳。
3、 Download任務。下載任務以文件形式獲取數(shù)據(jù),當APP不運行時,支持后臺下載。
和大部分網(wǎng)絡API一樣,NSURLSession的API是高度異步的。它會以下面兩種方式中的一種來返回數(shù)據(jù),取決于你調(diào)用的方法:
1、當傳輸成功完成或者傳輸錯誤時,調(diào)用完成處理的block;
2、當接收到數(shù)據(jù)或傳輸完成時,調(diào)用session的代理。
NSURLSession的API還提供了查詢狀態(tài)和進度的屬性,可以跟筠需要對任務當前的狀態(tài)(隨時注意狀態(tài)變化)來做一些項目決策。
URL會話也支持取消,重新開始,繼續(xù),掛起任務,并支持繼續(xù)下載掛起、下載取消、下載失敗的功能。
使用NSURLSession類請求:
1、創(chuàng)建一個session配置。對于后臺會話,這個配置必須包含唯一標識符。存儲標識符,當APP崩掉或結束掛起時,使用它來重連會話。
2、創(chuàng)建會話,指定配置對象和代理。
3、在會話中創(chuàng)建任務對象,每個任務代表一個URL請求。
這些任務對象是NSURLSessionTask——NSURLSessionDataTask, NSURLSessionUploadTask, NSURLSessionDownloadTask,取決于你創(chuàng)建的方式。
每個任務的初始狀態(tài)都是都是暫停狀態(tài)。APP在任務中調(diào)用resume方法后,就開始下載指定資源。
開始任務后,會話調(diào)用代理方法的步驟:
1、如果與服務器第一次握手需要連接的身份認證(如SSL客戶端認證),NSURLSession會調(diào)用代理方法
URLSession:task:didReceiveChallenge:completionHandler:
或
URLSession:didReceiveChallenge:completionHandler:
2、如果任務的數(shù)據(jù)從流中獲取,NSURLSession調(diào)用代理方法
URLSession:task:needNewBodyStream:
來獲取NSInputStream的實例為新的請求提供body數(shù)據(jù)。
3、在body內(nèi)容第一次上傳到服務器期間,代理定期會收到回調(diào)
URLSession:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:
來報告上傳的進度。
4、服務器發(fā)送響應。
5、如果響應指明要求認證,會話調(diào)用代理的
URLSession:task:didReceiveChallenge:completionHandler:
方法。回到第2步。
6、如果響應是HTTP重定向響應,NSURLSession對象調(diào)用代理的方法
URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler:
代理方法使用所提供的NSURLRequest對象(遵循重定向),一個新的NSURLRequest對象(重定向到不同URL),或者nil(將重定向的響應體作為有效響應并作為結果返回)來調(diào)用所提供的completion處理回調(diào)。
如果要遵循重定向,回到第2步。
如果代理沒有實現(xiàn)這個方法,重定向追蹤最大重定向數(shù)。
7、對于通過調(diào)用
downloadTaskWithResumeData:
或
downloadTaskWithResumeData:completionHandler:
創(chuàng)建的下載(或重下載)任務,NSURLSession使用新任務對象調(diào)用代理方法
URLSession:downloadTask:didResumeAtOffset:expectedTotalBytes:
8、對于數(shù)據(jù)任務,NSURLSession對象調(diào)用代理方法
URLSession:dataTask:didBecomeDownloadTask:
,來決定是否轉(zhuǎn)變數(shù)據(jù)任務為下載任務,然后調(diào)用處理回調(diào)來轉(zhuǎn)變,繼續(xù),取消任務。如果APP選擇將數(shù)據(jù)任務轉(zhuǎn)變?yōu)橄螺d任務,NSURLSession會使用新下載任務作為參數(shù)調(diào)用代理的方法。調(diào)用之后,代理不會收到來自數(shù)據(jù)任務的進一步回調(diào),而是開始收到來自下載任務的回調(diào)。
9、在從服務器傳輸?shù)倪^程中,代理會定時的收到任務的回調(diào)來報告?zhèn)鬏數(shù)倪M度。
對于數(shù)據(jù)任務,會話使用他們收到的原始數(shù)據(jù)調(diào)用代理的方法
URLSession:dataTask:didReceiveData:
對于下載任務,會話使用成功寫入磁盤的字節(jié)數(shù)調(diào)用代理的方法
URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:
如果用戶告訴APP暫停下載,通過調(diào)用
cancelByProducingResumeData:
方法取消任務。
最后,如果用戶告訴APP繼續(xù)下載,那么需要傳遞已經(jīng)返回的resume數(shù)據(jù)給
downloadTaskWithResumeData:
方法或
downloadTaskWithResumeData:completionHandler:
方法來創(chuàng)建新的下載任務來繼續(xù)下載。(回到第1步)。
10、對于數(shù)據(jù)任務,NSURLSession對象可調(diào)用
URLSession:dataTask:willCacheResponse:completionHandler:
方法。然后APP決定是否允許緩存。如果你沒有實現(xiàn)這個方法,默認的方式是使用會話的配置對象中指定的緩存策略。
11、如果響應是多部分編碼的,會話可再次調(diào)用代理的didReceiveResponse方法,然后不調(diào)用或者多次調(diào)用didReceiveData。如果這樣的情況發(fā)生了,那么請轉(zhuǎn)至步驟8(處理didReceiveResponse調(diào)用)。
12、如果下載任務成功完成,那么NSURLSession對象使用臨時文件的位置調(diào)用任務的
URLSession:downloadTask:didFinishDownloadingToURL:
方法。APP必須在代理方法返回前,要么從這個文件中讀取響應數(shù)據(jù),要么把它移動到持久存儲的位置。
13、當任務完成時,NSURLSession對象使用一個error對象或者nil(如果任務成功完成)調(diào)用代理的方法
URLSession:task:didCompleteWithError:
如果下載任務繼續(xù),NSError對象的userInfo字典包含了NSURLSessionDownloadTaskResumeData 鍵的值。APP傳遞這個值來調(diào)用方法
downloadTaskWithResumeData:
或方法
downloadTaskWithResumeData:completionHandler:
來創(chuàng)建新的下載任務來繼續(xù)存在的下載。
如果任務沒有被繼續(xù),APP就會創(chuàng)建一個新的下載任務并從開始重啟事件。
這兩種情況下,如果傳輸失敗,如果不是服務器原因,請轉(zhuǎn)至步驟3(創(chuàng)建和繼續(xù)任務)。
14、如果不再需要會話,我們可以通過調(diào)用invalidateAndCancel(取消任務)或finishTasksAndInvalidate (允許任務來在廢棄之前完成)。
如果沒有廢棄會話,當APP終止時,它會自動消失(除非是具有活動任務的后臺會話)。
在廢棄會話后,當所有的任務被取消或完成時,會話會調(diào)用代理的URLSession:didBecomeInvalidWithError:方法。
當代理方法返回時,會話釋放代理的強引用。
如果APP取消了正在進行的下載,雖然會發(fā)生錯誤,NSURLSession對象還是會調(diào)用代理的 URLSession:task:didCompleteWithError:方法。
URL會話的API都是完全線程安全的。可任意創(chuàng)建會話和任務。代理方法調(diào)用完成處理回調(diào)時,會在代理隊列中被自動適當安排。
會話和任務都遵守NSCopying協(xié)議,當copy一個會話或者任務時,我們會得到一個相同對象。而當copy一個配置對象時,我們會得到一個新的對象,可以獨立的修改。
App Transport Security (ATS)應用傳輸安全
在iOS9.0和 OS X10.11開始出現(xiàn),對于使用NSURLSession的所有HTTP連接,默認會啟用這個叫做ATS的新安全功能。ATS要求HTTP連接使用HTTPS(RFC 2818)。
使用Block來處理請求
(1)、Data任務
//1、創(chuàng)建單例會話
NSURLSession *session = [NSURLSession sharedSession];
//2、創(chuàng)建請求和任務對象
NSURL *url = [NSURL URLWithString:@"http://www.lxweimin.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(@"請求成功 = %@", dataStr);
? ? }
? ? else
? ? {
? ? ? ? NSLog(@"請求失敗");
? ? }
}];
[dataTask resume];
//1、創(chuàng)建單例會話
NSURLSession *session = [NSURLSession sharedSession];
//2、創(chuàng)建請求和任務對象
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)建單例會話
NSURLSession *session = [NSURLSession sharedSession];
//2、創(chuàng)建請求和任務對象
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/個人相關/天籟小學.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任務
在這里使用NSURLSessionDataDelegate代理的方法來處理請求
{
? ? //1、創(chuàng)建會話配置
? ? NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
? ? configuration.allowsCellularAccess = NO;
? ? configuration.timeoutIntervalForRequest = 10;
? ? //2、創(chuàng)建單例會話
? ? NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:[NSOperationQueue mainQueue]];
? ? //3、創(chuàng)建請求和任務對象
? ? NSURL *url = [NSURL URLWithString:@"http://www.lxweimin.com/u/8ca9e2a2536a"];
? ? NSURLSessionDataTask *dataTask = [session dataTaskWithURL:url];
? ? [dataTask resume];
}
#pragma mark -NSURLSessionDataDelegate
//接收到服務器響應
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
didReceiveResponse:(NSURLResponse *)response
completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler
{
? ? completionHandler(NSURLSessionResponseAllow);// 允許處理服務器的響應,才會繼續(xù)接收服務器返回的數(shù)據(jù)
}
//接收服務器回傳的數(shù)據(jù),有可能執(zhí)行多次
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
? ? didReceiveData:(NSData *)data
{
? ? if (data)
? ? {
? ? ? ? NSString *dataStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
? ? ? ? NSLog(@"請求成功 = %@", dataStr);
? ? }
? ? else
? ? {
? ? ? ? NSLog(@"請求失敗");
? ? }
}
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
willCacheResponse:(NSCachedURLResponse *)proposedResponse
completionHandler:(void (^)(NSCachedURLResponse * _Nullable cachedResponse))completionHandler
{
}
{
? ? //1、創(chuàng)建會話配置
? ? NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
? ? configuration.allowsCellularAccess = NO;
? ? configuration.timeoutIntervalForRequest = 10;
? ? //2、創(chuàng)建單例會話
? ? NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:[NSOperationQueue mainQueue]];
? ? //3、創(chuàng)建請求和任務對象
? ? NSURL *url = [NSURL URLWithString:@"http://www.lxweimin.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ù)據(jù)大小,當每次寫入臨時文件時,就會調(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
{
? ? //打印下載進度
? ? NSLog(@"%f",totalBytesWritten * 1.0 / totalBytesExpectedToWrite);
}
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
didResumeAtOffset:(int64_t)fileOffset
expectedTotalBytes:(int64_t)expectedTotalBytes
{
}
//1、創(chuàng)建會話配置
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
configuration.allowsCellularAccess = NO;
configuration.timeoutIntervalForRequest = 10;
//2、創(chuàng)建單例會話
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:[NSOperationQueue mainQueue]];
//3、創(chuàng)建請求和任務對象
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/個人相關/天籟小學.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];
- (IBAction)startDonload:(id)sender
{
? ? //1、創(chuàng)建會話配置
? ? NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
? ? configuration.allowsCellularAccess = NO;
? ? configuration.timeoutIntervalForRequest = 10;
? ? //2、創(chuàng)建單例會話
? ? NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:[NSOperationQueue mainQueue]];
? ? self.session = session;
? ? //3、創(chuàng)建請求和任務對象
? ? 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ù)保存起來,以備斷點續(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);
}