本文转载自:吕阿蒙
网络--通信过程
请求
请求头:包含了对客户端的环境描述、客户端请求信息等
Host 客户端想访问的服务器主机地址
User-Agent 客户端的类型,客户端的软件环境
Accept 客户端所能接收的数据类型
Accept-Language 客户端的语言环境
Accept-Encoding 客户端支持的数据压缩格式
请求体:客户端发给服务器的具体数据,比如文件数据(POST请求才会有)
响应
客户端向服务器发送请求,服务器应当做出响应,即返回数据给客户端
响应头:包含了对服务器的描述、对返回数据的描述
Server 服务器的类型
Content-Type 返回数据的类型
Content-Length 返回数据的长度
Date 响应的时间
响应体:服务器返回给客户端的具体数据,比如文件数据
网络--JSON
NSJSONSerialization(序列化工具)
NSJSONSerialization常见方法
JSON数据->OC对象
/*
1.JSON的二进制数据
2.枚举值
3.错误信息
*/
/* NSJSONReadingOptions
NSJSONReadingMutableContainers = (1UL << 0),可变字典和数组
NSJSONReadingMutableLeaves = (1UL << 1), 内部所以的字符串都是可变的,iOS7之后有问题 ,一般不用
NSJSONReadingAllowFragments = (1UL << 2) 既不是字典也不是数组,则必须使用该枚举值
*/
+ (nullable id)JSONObjectWithData:(NSData *)data options:(NSJSONReadingOptions)opt error:(NSError **)error;
OC对象->JSON数据
/*
注意:并不是所有的OC对象都能转换为JSON
最外层必须是NSArray or NSDictionary
所有的元素必须是NSArray,NSNumber,NSArray,NSDictory,or NSNull
字典中所有的key都必须是NSString类型的
NSNumber不能无穷大
*/
/*
1.要转换的OC对象
2.排序选项
NSJSONWritingPrettyPrinted 排版 美观,但会改变原来的顺序
NSJSONWritingSortedKeys 原来dic是什么顺序,输出还是什么顺序,对于JSON有顺序要求的选择这个
*/
+ (nullable NSData *)dataWithJSONObject:(id)obj options:(NSJSONWritingOptions)opt error:(NSError **)error;
网络--NSURLSession
使用步骤
使用NSURLSession对象创建Task,然后执行Task 注意:请求在子线程调用
GET请求
- (void)get{
//确定URL
NSURL *url = [NSURL URLWithString:@"url"];
//创建请求对象
NSURLRequest *quest = [NSURLRequest requestWithURL:url];
//创建会话对象
NSURLSession *session = [NSURLSession sharedSession];
//创建Task
//方法一
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:quest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
}];
//方法二
//内部会自动将请求路径作为参数创建一个请求对象(GET)
NSURLSessionDataTask *dataTask = [session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
}];
//执行Task
[dataTask resume];
}
POST请求
- (void)post{
//确定URL
NSURL *url = [NSURL URLWithString:@"url"];
//创建请求对象
NSMutableURLRequest *quest = [NSMutableURLRequest requestWithURL:url];
//设置请求方法为POST
quest.HTTPMethod = @"POST";
//设置请求体
quest.HTTPBody = [@"user=sas&pwd=123" dataUsingEncoding:NSUTF8StringEncoding];
//创建会话对象
NSURLSession *session = [NSURLSession sharedSession];
//创建Task
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:quest completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
}];
//执行Task
[dataTask resume];
}
代理
- (void)delegateTask{
NSURL *url = [NSURL URLWithString:@"url"];
//创建请求对象
NSURLRequest *quest = [NSURLRequest requestWithURL:url];
/*
1.配置信息 [NSURLSessionConfiguration defaultSessionConfiguration]
2.代理
3.设置代理方法在哪个线程中调用
*/
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
//创建Task
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:quest];
//执行Task
[dataTask resume];
}
#pragma mark - NSURLSessionDataDelegate
/**
接收服务器的响应 他默认会取消该请求
@param session 会话对象
@param dataTask 请求任务
@param response 响应头信息
@param completionHandler 回调 传给系统
*/
- (void)URLSession:(NSURLSession *)session dataTask:(nonnull NSURLSessionDataTask *)dataTask didReceiveResponse:(nonnull NSURLResponse *)response completionHandler:(nonnull void (^)(NSURLSessionResponseDisposition))completionHandler{
/*NSURLSessionResponseCancel = 0,取消 默认
NSURLSessionResponseAllow = 1, 接收
NSURLSessionResponseBecomeDownload = 2, 变成下载任务
NSURLSessionResponseBecomeStream 变成下载任务
*/
completionHandler(NSURLSessionResponseAllow);
}
/**
接收到服务器返回的数据 调用多次
@param session 会话对象
@param dataTask 请求任务
@param data 本次下载的数据
*/
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data{
[self.fileData appendData:data];
}
/**
请求结束或者是失败的时候调用
@param session 会话对象
@param task 请求任务
@param error 错误信息
*/
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{
//解析数据
NSLog(@"%@",[[NSString alloc]initWithData:self.fileData encoding:kCFStringEncodingUTF8]);
}
NSURLSessionDownloadTask 大文件下载
- (void)download{
NSURL *url = [NSURL URLWithString:@"url"];
//创建请求对象
NSURLRequest *quest = [NSURLRequest requestWithURL:url];
//创建session
NSURLSession *session = [NSURLSession sharedSession];
/**
创建task
@param location 下载路径
@param response 响应头信息
@param error 错误信息
*/
//该方法内部已经实现了边接收数据边写沙盒(tmp)的操作
//由于是临时文件夹,所以不会长久保存
//缺点:无法监听下载进度
//优点:不用担心内存
NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:quest completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
//拼接文件全路径
NSString *fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]stringByAppendingPathComponent:response.suggestedFilename];
//剪切文件
[[NSFileManager defaultManager]moveItemAtURL:location toURL:[NSURL URLWithString:fullPath] error:nil];
}];
[downloadTask resume];
}
离线断点下载
@property (nonatomic, strong) NSURLSessionDataTask *task;
@property (nonatomic, assign) NSInteger currentSize;
@property (nonatomic, assign) NSInteger totalSize;
@property (nonatomic, strong) NSString *fullPath;
@property (nonatomic, strong) NSFileHandle *handle;//文件句柄
@property (nonatomic, strong) NSURLSession *session;
- (NSURLSession *)session{
if (_session == nil) {
_session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
}
return _session;
}
-(NSString *)fullPath{
if (_fullPath == nil) {
_fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]stringByAppendingPathComponent:@"111.mp4"];
}
return _fullPath;
}
- (NSURLSessionDataTask *)task{
if (_task == nil) {
NSURL *url = [NSURL URLWithString:@"url"];
//创建请求对象
NSMutableURLRequest *quest = [NSMutableURLRequest requestWithURL:url];
//获取指定文件s路径对应文件的数据大小
self.currentSize = [self getFileSize];
//设置请求头,告诉服务器请求哪一部分数据
NSString *range = [NSString stringWithFormat:@"bytes=%zd-",self.currentSize];
[quest setValue:range forHTTPHeaderField:@"Range"];
//创建Task
_task= [self.session dataTaskWithRequest:quest];
}
return _task;
}
- (NSInteger)getFileSize{
NSDictionary * info = [[NSFileManager defaultManager]attributesOfItemAtPath:self.fullPath error:nil];
NSInteger currentSize = [info[@"NSFileSize"] integerValue];
return currentSize;
}
#pragma mark - NSURLSessionDataDelegate
- (void)URLSession:(NSURLSession *)session dataTask:(nonnull NSURLSessionDataTask *)dataTask didReceiveResponse:(nonnull NSURLResponse *)response completionHandler:(nonnull void (^)(NSURLSessionResponseDisposition))completionHandler{
self.totalSize = response.expectedContentLength+self.currentSize;
if (self.currentSize == 0) {
//创建空文件
[[NSFileManager defaultManager]createFileAtPath:self.fullPath contents:nil attributes:nil];
}
//创建文件句柄
self.handle = [NSFileHandle fileHandleForWritingAtPath:self.fullPath];
//移动指针
[self.handle seekToEndOfFile];
completionHandler(NSURLSessionResponseAllow);
}
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data{
//写入数据到文件
[self.handle writeData:data];
self.currentSize += data.length;
}
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{
//解析数据
[self.handle closeFile];
self.handle = nil;
}
- (void)dealloc{
//清理工作
//[self.session finishTasksAndInvalidate]
[self.session invalidateAndCancel];
}
文件上传
- (void)upload{
NSURL *url = [NSURL URLWithString:@"aa"];
//创建请求对象
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
//设置请求方法
request.HTTPMethod = @"POST";
//设置请求头信息
NSString *boundary = @"----WebKitFormBoundary8vNspBm1CiPXHhA5";//分隔符
[request setValue:[NSString stringWithFormat:@"multipart/form-data;boundary=%@",boundary] forHTTPHeaderField:@"Content-Type"];
//创建会话对象
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue] ];
//创建上传task
/*
1.请求对象
2.传递要上传的数据
3.
*/
NSURLSessionUploadTask *task = [session uploadTaskWithRequest:request fromData:[self getBodyData] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
}];
[task resume];
}
- (NSData *)getBodyData{
return [NSData data];
}
///
/// @param session session
/// @param task task
/// @param bytesSent 本次发送的数据
/// @param totalBytesSent 上传完成的数据大小
/// @param totalBytesExpectedToSend 文件的总大小
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend{
NSLog(@"%f",1.0*totalBytesSent/totalBytesSent);
}