3.0版本之后,AFN跟着苹果从NSURLConnection全面升级为NSURLSession,废弃了AFURLConnectionOperation,并且全面简化了API,规范了逻辑文件夹。
AFURLSessionManager
核心类,主要是通过对NSURLSession和NSURLSessionTask的封装实现网络请求的各种功能。子类是AFHTTPSessionManager,优化了针对http的请求API。
初始化和配置
1、Serializer
设置网络请求的序列化对象:满足AFURLRequestSerialization协议的AFHTTPRequestSerializer对象(当然还有别的子类),配置请求的cookies,timeout,字符串编码方式(stringEncoding),http的headertype,user-agent等。
设置返回数据的序列化对象:满足AFURLResponseSerialization协议的AFHTTPResponseSerializer对象(JSON、XML等其他对象默认配置了statuscode和contenttypes),配置返回数据的acceptableStatusCodes和acceptableContentTypes,检查返回数据是否合法并进行转化。
注:AFJSONResponseSerializer序列化对象的底层是使用Foundation中内置的NSJSONSerialization对象实现的。
2、AFSecurityPolicy
用于HTTPS中的SSL校验规则设置,验证证书是否正确。
3、AFNetworkReachabilityManager
startMonitoring监听网络状态的变化。
Task的创建和获取
task只读对象有:tasks,dataTasks,uploadTasks,downloadTasks数组,数组内对象满足NSURLSessionTask等的协议,分别对应,全部、数据、上传和下载的任务数组。
task的创建:dataTaskWithRequest、uploadTaskWithRequest(分为fileRUL/data/request这三个数据源)、downloadTaskWithRequest等,可根据选择不同参数的方法。
注:所有的task创建都不在主线程。
注:downloadTaskWithResumeData恢复下载的数据(下载时要随时保存resumeData用于下次继续下载时的恢复),底层继承于NSURLSession的同名方法,可获取到task。
代理的实现和通知的定义
AFURLSessionManager实现了NSURLSessionDelegate、NSURLSessionTaskDelegate、NSURLSessionDataDelegate、NSURLSessionDownloadDelegate四个代理,然后暴露了实现代理后的各种block回调,用于处理各种过程或结束状态时的数据。如,setSessionDidBecomeInvalidBlock(session无效或出错的回调),setDataTaskDidReceiveResponseBlock(接收到网络请求返回后)。
还能通过AFNetworkingTaskDidResumeNotification、AFURLSessionDidInvalidateNotification等通知KVO监听session的各种状态来处理业务逻辑。
应用
对AFHTTPSessionManager进行再一次封装(单例),根据需求配置请求和响应的Serializer,还可以监听网络状态等。所有方法都直接返回NSURLSessionDataTask可用于suspend和resume(暂停和继续)。
暴露GET、POST等方法,根据是否使用缓存,是否登录等参数进行方法提取。
- (__kindof NSURLSessionTask*)get/postRequest:(NSString*)URL
parameters:(id)parameters
shouldLogin:(BOOL)shouldLogin
responseCache:(HttpRequestCache)responseCache
success:(HttpRequestSuccess)success
failure:(HttpRequestFailed)failure;
暴露uploadFileWithURL、uploadImagesWithURL、downloadWithURL等方法,传入具体数据、路径等。如上传图片:
- (__kindof NSURLSessionTask*)uploadImagesWithURL:(NSString*)URL
parameters:(id)parameters
name:(NSString*)name //图片名
images:(NSArray *)images //与数据有关的名字
fileNames:(NSArray *)fileNames
imageScale:(CGFloat)imageScale //压缩比
progress:(HttpProgress)progress
success:(HttpRequestSuccess)success
failure:(HttpRequestFailed)failure;
断点续传
首先断点续传一般指的是下载,但这里上传和下载都写写。
上传
原理:将要上传的数据二进制写入httpbody中,可在request header中提供一些元数据如文件名等。
方法:uploadTaskWithRequest: fromFile: / fromData: (不使用表单)
uploadTaskWithStreamedRequest:(使用表单)
对应到AFHTTPSessionManager中为 POST: parameters: constructingBodyWithBlock: success: failure: 方法(该方法在constructingBodyWithBlock中应使用appendPartWithXXX来设置AFMultipartFormData表单数据)。
构建StreamedRequest的原理:requestSerializer中的multipartFormRequestWithMethod方法,底层通过appendPartWithFormData: name: 设置Content-Type:multipart/form-data; boundary=%@ 提供分割/拼接依据:
Content-Type: multipart/form-data; boundary=----这里是随机boundary
----这里是随机boundary
Content-Disposition: form-data; name="key"
value
----这里是随机boundary
Content-Disposition: form-data; name="imgFile"; filename="no-file"
Content-Type: application/octet-stream
----这里是随机boundary
分片上传:大文件上传的中断和继续要用到分片原理:使用NSFileHandle中的seekToFileOffset和readDataOfLength等方法,把文件分割成大小合适的data,对写入httpbody中的data的数据格式进行改造加入标识(即表单提交),需要服务器脚本支持。
分片上传可通过标识分片在文件中的位置来实现通过多线程并行上传,当然要结合网络和负载设置最大并发数。
注:表单提交是分片上传的基础,因为要提供拼接依据。
断点续传:切片时做好分片唯一标示,每上传成功一个分片都应该记录finish,恢复上传时判断,只上传未被finish的分片。
注:阿里云七牛等SDK提供了比较方便的分片上传和断点续传的接口。
下载
原理:http请求头中有个Range关键字设置bytes=100-999,表示返回哪些字节,得到的data利用seekToEndOfFile+writeData拼接在文件后。NSURLSessionDownloadTask已经封装好了,其返回的resumeData包含了路径key和range这些请求信息。
方法:downloadTaskWithRequest、downloadTaskWithResumeData,方法返回NSURLSessionDownloadTask对象。
暂停和恢复:NSURLSessionDownloadTask提供cancelByProducingResumeData方法,它会让task暂停并且返回可供再次开启的ResumeData。使用downloadTaskWithResumeData方法再次开启。
注:若要实现杀掉app的断点续传,需要在progress中定期保存data进度(定期暂停获取resumeData比较方便但效率低方法蠢,手动记录比较复杂,需要本地维护锚点数据和操作文件读写)。推荐SRDownloadManager。
网友评论