基本概念: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下载地址: