HTTP
1.面试题:聊一下 HTTP 协议(表达对 HTTP 协议的看法)
解析:问的点 就是 关于 协议的完整的通信过程
* 全称:超文本传输协议,定制传输数据的规范(客户端和服务器之间的数据传输规范)
* 描述 HTTP 协议完整的通信过程
解答:
① 请求:
*客户端–>服务器
*请求内容
a.请求行 (请求方法//资源路径 /HTTP 协议/)
PS:GET /MJServer/login?username=123&pwd=123&type=JSON HTTP/1.1
b.请求头 (描述客户端的信息)
PS:Host:192.168.1.20:8080
User-Agent:Mozilla/5.0(Macintosh;Intel Mac OS X 10.9 ;rv:26.0)
c. 请求体 (POST需要存放具体数据)
*比如文件数据
* POST 请求的数据参数
② 响应
*服务器–>客户端
*响应内容
a.状态行 (响应行 /状态码/状态信息(响应行))
PS:HTTP/1.1 200 OK
b.响应头(服务器信息,返回时间的类型,返回数据的长度)
PS:Server:Apache-Coyote/1.1
Content-Type:application/json,charset=UTF-8
content-Length:248
c.实体内容(返回给客户端的具体内容,也可以叫响应体,);
*服务器返回的 JSON 数据/文件数据
头信息 是描述 对请求信息 返回信息的描述
行信息 是状态 就你要请求什么东西
体里面 是放二进制数据
2.请求方法
1>GET
* 参数:都拼在 URL 后面 并且有限制
2>POST
* 参数:都在请求体中 无限制
* 上传只能用 POST
3>HEAD: 获得响应头信息 不获取响应体
3.IOS 发送 GET/POST 的手段
1>NSURLConnection
*苹果原生
*相比2>3> 复杂
2>ASIHTTP
*基于 CFNetWork
*提供非常强大的功能 使用简单
3>AFNetWorking
*基于 NSURLConnection 提供常用功能
注:
①为了提高开发效率和减少调试花费的时间 ,尽量使用著名的简单第三方框架;
②处理 HTTP 建议使用 ASI /AFN
1> NSURLConnection
* 发送一个同步请求
+ (NSData *)sendSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse **)response error:(NSError **)error;
- 发送一个异步请求
+ (void)sendAsynchronousRequest:(NSURLRequest*) request
queue:(NSOperationQueue*) queue
completionHandler:(void (^)(NSURLResponse* response, NSData* data, NSError* connectionError)) handler;
- 代理的方法(异步)
[NSURLConnection connectionWithRequest:request delegate:self];
[[NSURLConnection alloc] initWithRequest:request delegate:self];
[[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO];
[conn start];
2.文件下载(大文件)
1>实现方案:边下载边写入(写道沙盒中的某个文件中)
2>具体实现步骤
a.在接受服务器响应时
#pragma mark - NSURLConnectionDataDelegate 代理方法
/**
* 1. 当接受到服务器的响应(连通了服务器)就会调用
*/
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
#warning 一定要判断
if (self.totalLength) return;
// 1.创建一个空的文件到沙盒中
NSFileManager *mgr = [NSFileManager defaultManager];
// 刚创建完毕的大小是0字节
[mgr createFileAtPath:self.destPath contents:nil attributes:nil];
// 2.创建写数据的文件句柄
self.writeHandle = [NSFileHandle fileHandleForWritingAtPath:self.destPath];
// 3.获得完整文件的长度
self.totalLength = response.expectedContentLength;
}
b. 在接受到服务器的数据时
*利用句柄对象将服务器放哪的数据写道文件末尾
/**
* 2. 当接受到服务器的数据就会调用(可能会被调用多次, 每次调用只会传递部分数据)
*/
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
// 累加长度
self.currentLength += data.length;
// 显示进度
double progress = (double)self.currentLength / self.totalLength;
if (self.progressHandler) { // 传递进度值给block
self.progressHandler(progress);
}
// 移动到文件的尾部
[self.writeHandle seekToEndOfFile];
// 从当前移动的位置(文件尾部)开始写入数据
[self.writeHandle writeData:data];
}
c.在接收完服务器返回的数据时 关闭句柄
/**
* 3. 当服务器的数据接受完毕后就会调用
*/
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
// 清空属性值
self.currentLength = 0;
self.totalLength = 0;
if (self.currentLength == self.totalLength) {
// 关闭连接(不再输入数据到文件中)
[self.writeHandle closeFile];
self.writeHandle = nil;
}
if (self.completionHandler) {
self.completionHandler();
}
}
3.断点下载
!!!!关键技术点: 设置请求头 Range,告诉服务器从哪一段开始下载
4.文件下载
1>明确
*只能用 POST
* 请求参数都在请求体中(文件参数/非文件类型的普通参数)
2>实现步骤
a. 拼接请求体(文件参数/非文件类型的普通参数)
*文件参数
/***************文件参数***************/
// 参数开始的标志
[body appendData:HMEncode(@"--heima\r\n")];
// name : 指定参数名(必须跟服务器端保持一致)
// filename : 文件名
NSString *disposition = [NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\"\r\n", name, filename];
[body appendData:HMEncode(disposition)];
NSString *type = [NSString stringWithFormat:@"Content-Type: %@\r\n", mimeType];
[body appendData:HMEncode(type)];
[body appendData:HMEncode(@"\r\n")];
[body appendData:data];
[body appendData:HMEncode(@"\r\n")];
*普通参数
/***************普通参数***************/
[params enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
// 参数开始的标志
[body appendData:HMEncode(@"--heima\r\n")];
NSString *disposition = [NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"\r\n", key];
[body appendData:HMEncode(disposition)];
[body appendData:HMEncode(@"\r\n")];
[body appendData:HMEncode(obj)];
[body appendData:HMEncode(@"\r\n")];
}];
b. 设置请求头
*请求体长度
Content -Length: 请求体的长度(字节长度)
*请求数据的类型
Content-Type:
//普通 POST :application/x-www-form-urlencoded
//上传文件的 POST 请求: multipart/form-data; boundary=–heima