基本概念:php
客戶端(Client):移動應用(iOS,Andorid等應用)
服務器(Server):爲客戶端提供服務、提供數據、提供資源的機器
請求(Request):客戶端向服務器索取數據的⼀種行爲
響應(Response):服務器對客戶端的請求作出的反應,⼀般指返回數據給客戶端html
##一、URLgit
1.基本介紹github
URL的全稱是Uniform Resource Locator(統⼀資源定位符) 經過1個URL,能找到互聯⺴上惟一的1個資源json
URL就是資源的地址、位置,互聯網上的每一個資源都有一個惟一的URLapi
URL的基本格式 = 協議://主機地址/路徑 http://61.144.56.195/forum/201302/19/144736txfrcuyvmustucmv.jpg http://www.fzlu.com/uploads/allimg/140107/1-14010G22134235.jpg瀏覽器
協 議:不一樣的協議表明不一樣的資源查找方式、資源傳輸方式緩存
主機地址:存放資源的主機的IP地址(域名)安全
路 徑:資源在主機中的具體位置服務器
2.URL中常見的協議
a.HTTP:超文本傳輸協議,訪問的是遠程的⺴絡資源,格式是http:// http協議是在網絡開發中最經常使用的協議
b.file:訪問的是本地計算機上的資源,格式是file://(不用加主機地址)
c.mailto:訪問的是電子郵件地址,格式是mailto:
d.FTP:訪問的是共享主機的⽂文件資源,格式是ftp://
##二、HTTP協議
1.HTTP協議簡介 不論是移動客戶端仍是PC端,訪問遠程的⺴絡資源常用HTTP協議
訪問百度主⻚頁:http://www.baidu.com 得到新浪的微博數據 得到⼤大衆點評的團購數據
2.HTTP協議的做用
HTTP的全稱是Hypertext Transfer Protocol,超⽂本傳輸協議
(1)規定客戶端和服務器之間的數據傳輸格式
(2)讓客戶端和服務器能有效地進行數據溝通
##三、HTTP通訊過程:請求和響應
1.HTTP請求
HTTP協議規定,1個完整的由客戶端發給服務器的HTTP請求中包含如下內容
請求行:包含了請求方法、請求資源路徑、HTTP協議版本 GET /MJServer/resources/images/1.jpg HTTP/1.1
請求頭:包含了對客戶端的環境描述、客戶端請求的主機地址等信息
Host: 192.168.1.105:8080 // 客戶端想訪問的服務器主機地址
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9) Firefox/30.0// 客戶端的 類型,客戶端的軟件環境
Accept: text/html, /// 客戶端所能接收的數據類型 Accept-Language: zh-cn // 客戶端的語言環境
Accept-Encoding: gzip // 客戶端支持的數據壓縮格式 請求體:客戶端發給服務器的具體數據,好比文件數據
2.HTTP響應
客戶端向服務器發送請求,服務器應當作出響應,即返回數據給客戶端
HTTP協議規定:1個完整的HTTP響應中包含如下內容:
狀態行:包含了HTTP協議版本、狀態碼、狀態英⽂名稱HTTP/1.1 200 OK
響應頭:包含了對服務器的描述、對返回數據的描述 Server: Apache-Coyote/1.1 // 服務器的類型
Content-Type: image/jpeg // 返回數據的類型
Content-Length: 56811 // 返回數據的長度
Date: Mon, 23 Jun 2014 12:54:52 GMT // 響應的時間 實體內容:服務器返回給客戶端的具體數據,⽐好比⽂件數據
3.HTTP常見狀態響應碼
狀態碼 | 英文名稱 | 中文描述 |
---|---|---|
200 | OK | 請求完成 |
400 | Bad Request | 客戶端請求的語法錯誤,服務器沒法解析 |
404 | Not Found | 服務器沒法根據客戶端的請求找到資源 |
500 | Internal Server Error | 服務器內部錯誤,沒法完成請求 |
##四、發送HTTP請求的方法 1.簡單說明
在HTTP/1.1協議中,定義了8種發送http請求的⽅方法 GET、POST、OPTIONS、HEAD、PUT、DELETE、TRACE、CONNECT、PATCH 根據HTTP協議的設計初衷,不一樣的⽅法對資源有不一樣的操做⽅式
PUT :增
DELETE :刪
POST:改
GET:查
提示:最經常使用的是GET和POST(實際上GET和POST都能辦到增刪改查)
2.get和post請求
要想使⽤GET和POST請求跟服務器進⾏交互,得先了解一個概念:參數就是傳遞給服務器的具體數據,好比登陸時的賬號、密碼
GET:在請求URL後面以?的形式跟上發給服務器的參數,多個參數之間用&隔開, ⽐如http://ww.test.com/login?username=123&pwd=234&type=JSON(因爲瀏覽器和 服務器對URL長度有限制,所以在URL後面附帶的參數是有限制的,一般不能超過1KB)
POST:發給服務器的參數所有放在請求體中(POST傳遞的數據量沒有限制)
3.get和post的選擇
(1)若是要傳遞⼤量數據,⽐如文件上傳,只能用POST請求
(2)GET的安全性比POST要差些,若是包含機密\敏感信息,建議用POST (3)若是僅是索取數據(數據查詢),建議使用GET
(4)若是是增長、修改、刪除數據,建議使⽤POST
1.基本流程
同步GET請求、同步POST請求,異步GET請求,異步POST請求
##六、GET請求
GET請求:獲取數據,把參數以URL的形式拼接傳給服務器,以 ? 分開URL地址和參數,& 拼接多個參數
1.建立一個URL
NSString *urlStr = @"https://route.showapi.com/213-4?showapi_appid=24110&showapi_timestamp=20160905154834&topid=5&showapi_sign=5d1ba1725827501e32238072e5960958"; NSURL *URL = [NSURL URLWithString:urlStr];
2.建立一個NSURLRequest 請求
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
三、建立NSURLSession
NSURLSession *session = [NSURLSession sharedSession];
四、由session建立一個請求數據的任務NSURLSessionDataTask,(會以異步的形式發送網絡請求,不會阻塞主線程)
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { // 執行完後 以block 返回結果,解析數據 NSDictionary *jsonData = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil]; NSLog(@"%@",jsonData); }];
五、開始執行網絡任務
[dataTask resume];
##七、POST請求
POST請求時要指明請求的方式HTTPMethod 爲 POST,參數以請求體 HTTPMethod 的形式傳入。
一、設置請求方式爲 POST
NSURL *url = [NSURL URLWithString:@"https://route.showapi.com/213-4"]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; request.HTTPMethod = @"POST";
二、設置請求體:把參數做爲NSData類型傳入
NSString *parmStr = [NSString stringWithFormat:@"showapi_appid=%@&showapi_timestamp=%@&topid=%@&showapi_sign=%@",APPID,@"20160905154834",@"5",SIGN]; request.HTTPBody = [parmStr dataUsingEncoding:NSUTF8StringEncoding];
3.建立一個NSURLRequest 請求
NSURLSession *session = [NSURLSession sharedSession];
四、由session建立一個請求數據的任務NSURLSessionDataTask,(會以異步的形式發送網絡請求,不會阻塞主線程)
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { if (error) { NSLog(@"%@",error); return; } // NSLog(@"%@",response); // 執行完後 以block 返回結果,解析數據 NSDictionary *jsonData = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil]; NSLog(@"%@",jsonData); }]; [dataTask resume];
###7.1 網絡請求配置
設置緩存策略:cachePolicy
NSURLRequestUseProtocolCachePolicy = 0, // 默認,使用緩存,當下一次請求時先判斷是否有緩存,有就使用緩存沒有才進行網絡請求,使用緩存時會先判斷緩存是否過時,過時的就從新請求網絡。 NSURLRequestReloadIgnoringLocalCacheData = 1, // 忽略緩存,不使用緩存 NSURLRequestReloadIgnoringLocalAndRemoteCacheData = 4, // 無視任何的緩存策略,不管是本地的仍是遠程的,老是從原地址從新下載 NSURLRequestReloadIgnoringCacheData = NSURLRequestReloadIgnoringLocalCacheData, NSURLRequestReturnCacheDataElseLoad = 2, 首先使用緩存不論是否過時,若是沒有本地緩存,才從原地址下載 NSURLRequestReturnCacheDataDontLoad = 3, 使用本地緩存,從不下載,若是本地沒有緩存,則請求失敗。此策略多用於離線操做 NSURLRequestReloadRevalidatingCacheData = 5, // Unimplemented
timeoutInterval: 設置請求超時的時間秒數
NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:0 timeoutInterval:10];
NSURLSessionConfiguration:配置網絡請求
defaultSessionConfiguration, 默認的模式,能夠緩存數據 ephemeralSessionConfiguration, 無痕瀏覽,不會有任何的緩存 backgroundSessionConfigurationWithIdentifier NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
經過 NSURLSessionConfiguration 設置緩存策略
configuration.requestCachePolicy = NSURLRequestUseProtocolCachePolicy; NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration];
###7.2 下載數據
在實際應用中咱們常常須要知道下載的進度,咱們能夠經過block和NSURLSessionDownloadDelegate
代理兩種方式來實現這點,
當咱們不須要監聽下載數據進度的時候就能夠用block方式 block方式:
建立URL
NSURL *url = [NSURL URLWithString:@"http://dl.stream.qqmusic.qq.com/108051051.mp3?vkey=4A95A0FCDFDC050E9D543841CA4A28AABD19F1973177DAB509EEBED09344D0A91A286D0800E7C58751A670CC429DB1118C98F8908C487284&guid=2718671044"];
建立Session並設置
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
建立一個下載任務
NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithURL:url completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) { if (error) { return; } // 二、設置保存文件的本地URL NSURL *docmentsURL = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; //拼接一個數據名,response suggestedFilename 自動獲取下載數據的名字.格式類型 NSURL *dataURL = [docmentsURL URLByAppendingPathComponent:[response suggestedFilename]]; NSError *moveError = nil; // 三、將下載的數據從臨時URL移動到指定的URL [[NSFileManager defaultManager] moveItemAtURL:location toURL:dataURL error:&moveError]; if (!moveError) { NSLog(@"保存成功"); } NSLog(@"%@",location); }];
啓動下載
[downloadTask resume];
當咱們須要監聽下載進度的時候就用代理 代理方式
簽定協議
@interface ViewController ()<NSURLSessionDownloadDelegate>
配置NSURLSession並設置代理,delegateQueue:代理執行的線程
NSURL *url = [NSURL URLWithString:@"https://github.com/AFNetworking/AFNetworking/archive/master.zip"]; NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]]; NSURLSessionDownloadTask *downTask = [session downloadTaskWithURL:url]; [downTask resume];
監聽下載進度
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite { // bytesWritten: 時間點下載的數據大小 totalBytesWritten:已經下載的數據大小,totalBytesExpectedToWrite: 下載文件的總大小 self.prograssView.prograss = (CGFloat)totalBytesWritten / (CGFloat)totalBytesExpectedToWrite; NSLog(@"%lld, %lld, %lld ",bytesWritten, totalBytesWritten, totalBytesExpectedToWrite); }
下載完成後調用
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location { NSLog(@"下載完成 %@",NSHomeDirectory()); // 一、設置保存文件的本地URL NSURL *docmentsURL = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; NSURL *dataURL = [docmentsURL URLByAppendingPathComponent:downloadTask.response.suggestedFilename]; NSError *moveError = nil; // 二、將下載的數據從臨時URL移動到指定的URL [[NSFileManager defaultManager] moveItemAtURL:location toURL:dataURL error:&moveError]; if (!moveError) { NSLog(@"保存成功"); } }
###7.3 上傳數據
上傳數據用POST方式上傳 上傳數據也有block和代理兩種方式
block方式 建立URL,可變請求,請求類型爲Post
NSURL *url = [NSURL URLWithString:@"http://www.imageshack.us/index.php"]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:0 timeoutInterval:20]; request.HTTPMethod = @"POST";
設置請求頭的上傳文件的內容格式(Content-Type) 爲圖片類型(image/jpeg)、()
[request setValue:@"image/jpeg" forHTTPHeaderField:@"Content-Type"];
設置請求頭的響應(Accept)的文本格式(text/html)
[request setValue:@"text/html" forHTTPHeaderField:@"Accept"]; NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
上傳方式一:把要上傳的數據保存爲NSData
NSData *imageData = UIImageJPEGRepresentation([UIImage imageNamed:@"image7.jpeg"], 0.5); NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request fromData:imageData completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { if (error) { NSLog(@"%@",error); } else { NSString *reuslt = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@ \n%@",response, reuslt); } }];
上傳方式二:使用文件所在的本地的URL
NSURL *fileURL = [[NSBundle mainBundle] URLForResource:@"image7" withExtension:@"jpeg"]; // NSURL *fileURL = [NSURL URLWithString:@"http://img.ivsky.com/img/tupian/pre/201507/01/yindian_meinv-001.jpg"]; NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request fromFile:fileURL completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { if (error) { NSLog(@"%@",error); } else { NSString *reuslt = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@ \n%@",response, reuslt); } }]; [uploadTask resume];
代理方式
簽定代理協議
@interface ViewController ()<NSURLSessionDataDelegate>
NSURL *url = [NSURL URLWithString:@"http://www.imageshack.us/index.php"]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:0 timeoutInterval:20]; request.HTTPMethod = @"POST";
設置請求頭,和響應內容
// 設置請求頭的上傳文件的內容格式(Content-Type) 爲圖片類型(image/jpeg)、() [request setValue:@"image/jpeg" forHTTPHeaderField:@"Content-Type"]; // 設置請求頭的響應(Accept)的文本格式(text/html) [request setValue:@"text/html" forHTTPHeaderField:@"Accept"];
把圖片轉換爲Data格式
NSData *imageData = UIImageJPEGRepresentation([UIImage imageNamed:@"image7.jpeg"], 0.5);
代理方式啓動下載
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]]; NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request fromData:imageData]; [uploadTask resume];
代理方法:
上傳完成後調用
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler { NSLog(@"%@",response); }
上傳出錯時調用
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(nullable NSError *)error { NSLog(@"%@",error); }
上傳的進度監聽
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend { NSLog(@"%lld %lld %lld", bytesSent, totalBytesSent, totalBytesExpectedToSend); }
##八、後臺下載數據
讓程序在後臺狀態本身下載任務,下載完成後屏幕上方顯示一個提示
簽定代理協議
@interface ViewController ()<NSURLSessionDownloadDelegate>
建立URL和請求
NSURL *url = [NSURL URLWithString:@"https://github.com/fuqinglin/MagicalRecord/archive/master.zip"]; NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:0 timeoutInterval:20];
設置網絡請求爲 backgroundSessionConfigurationWithIdentifier 後臺模式,後面接標識符
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"com.tens.background"];
建立NSURLSession,啓動下載任務
NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:[NSOperationQueue mainQueue]]; NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request]; [downloadTask resume];
代理方法: 下載完成
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location { NSLog(@"下載完成"); }
下載進度
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite { NSLog(@"%lld %lld %lld",bytesWritten, totalBytesWritten, totalBytesExpectedToWrite); }
後臺下載完調用
- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session { NSLog(@"後臺下載完成"); AppDelegate *delegate = [UIApplication sharedApplication].delegate; // 回調 AppDelegate 中 application: handleEventsForBackgroundURLSession: completionHandler: 中的block事件,處理下載完後的提示 if (delegate.backgroundCompletionHandler) { void (^completionHandler)() = delegate.backgroundCompletionHandler; completionHandler(); } }
在AppDelegate.m中註冊發送通知的權限
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // 註冊發送通知的權限 [application registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge | UIUserNotificationTypeSound | UIUserNotificationTypeAlert categories:nil]]; return YES; }
監聽後臺下載任務完成
- (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler { NSLog(@"------後臺下載完成"); self.backgroundCompletionHandler = completionHandler; [self notification]; }
發送本地通知
- (void)notification{ UILocalNotification *notification = [[UILocalNotification alloc] init]; notification.fireDate = [[NSDate date] dateByAddingTimeInterval:2]; notification.alertTitle = @"下載任務提示"; notification.alertBody = @"下載完成"; notification.soundName = UILocalNotificationDefaultSoundName; notification.applicationIconBadgeNumber = 1; [[UIApplication sharedApplication] scheduleLocalNotification:notification]; }
##九、第三方框架AFNetWorking使用更方便,功能更多,便捷
下載地址:AFNetWorking
Demo下載地址: