AFNetworking2.0源码解析<二>

Win11 C盘爆满别慌!手把手教你安全迁移AppData和用户文件夹(附一键脚本) 本文针对Win11 C盘空间不足问题,提供了一套安全有效的解决方案。通过深入解析用户目录结构,指导用户利用符号链接和Robocopy工具,将AppData、下载文档等占用大户迁移至其他分区,并附带了自动化脚本,从根本上实现C盘瘦身,同时确保系统稳定和数据安全。 阅读详情
 
本篇我们继续来看看AFNetworking的下一个模块 — AFURLRequestSerialization。
 
AFURLRequestSerialization用于帮助构建NSURLRequest,主要做了两个事情:
 
1.构建普通请求:格式化请求参数,生成HTTP Header。
2.构建multipart请求。
 
分别看看它在这两点具体做了什么,怎么做的。
 
1.构建普通请求
 
A.格式化请求参数
一般我们请求都会按key=value的方式带上各种参数,GET方法参数直接加在URL上,POST方法放在body上,NSURLRequest没有封装好这个参数的解析,只能我们自己拼好字符串。AFNetworking提供了接口,让参数可以是NSDictionary, NSArray, NSSet这些类型,再由内部解析成字符串后赋给NSURLRequest。
 
转化过程大致是这样的:
   
  1. @{ 
  2.      @"name" : @"bang", 
  3.      @"phone": @{@"mobile": @"xx", @"home": @"xx"}, 
  4.      @"families": @[@"father", @"mother"], 
  5.      @"nums": [NSSet setWithObjects:@"1", @"2", nil] 
  6. } 
  7. -> 
  8. @[ 
  9.      field: @"name", value: @"bang", 
  10.      field: @"phone[mobile]", value: @"xx", 
  11.      field: @"phone[home]", value: @"xx", 
  12.      field: @"families[]", value: @"father", 
  13.      field: @"families[]", value: @"mother", 
  14.      field: @"nums", value: @"1", 
  15.      field: @"nums", value: @"2", 
  16. ] 
  17. -> 
  18. name=bang&phone[mobile]=xx&phone[home]=xx&families[]=father&families[]=mother&nums=1&num=2 
第一部分是用户传进来的数据,支持包含NSArray,NSDictionary,NSSet这三种数据结构。
 
第二部分是转换成AFNetworking内自己的数据结构,每一个key-value对都用一个对象AFQueryStringPair表示,作用是最后可以根据不同的字符串编码生成各自的key=value字符串。主要函数是AFQueryStringPairsFromKeyAndValue,详见源码注释。
 
第三部分是最后生成NSURLRequest可用的字符串数据,并且对参数进行url编码,在AFQueryStringFromParametersWithEncoding这个函数里。
 
最后在把数据赋给NSURLRequest时根据不同的HTTP方法分别处理,对于GET/HEAD/DELETE方法,把参数加到URL后面,对于其他如POST/PUT方法,把数据加到body上,并设好HTTP头,告诉服务端字符串的编码。
 
B.HTTP Header
AFNetworking帮你组装好了一些HTTP请求头,包括语言Accept-Language,根据 [NSLocale preferredLanguages] 方法读取本地语言,高速服务端自己能接受的语言。还有构建 User-Agent,以及提供Basic Auth 认证接口,帮你把用户名密码做 base64 编码后放入 HTTP 请求头。详见源码注释。
 
C.其他格式化方式
HTTP请求参数不一定是要key=value形式,可以是任何形式的数据,可以是json格式,苹果的plist格式,二进制protobuf格式等,AFNetworking提供了方法可以很容易扩展支持这些格式,默认就实现了json和plist格式。详见源码的类AFJSONRequestSerializer和AFPropertyListRequestSerializer。
 
2.构建multipart请求
构建Multipart请求是占篇幅很大的一个功能,AFURLRequestSerialization里2/3的代码都是在做这个事。
 
A.Multipart协议介绍
Multipart是HTTP协议为web表单新增的上传文件的协议,协议文档是rfc1867,它基于HTTP的POST方法,数据同样是放在body上,跟普通POST方法的区别是数据不是key=value形式,key=value形式难以表示文件实体,为此Multipart协议添加了分隔符,有自己的格式结构,大致如下:
—AaB03x
content-disposition: form-data; name=“name"
bang
--AaB03x
content-disposition: form-data; name="pic"; filename=“content.txt"
Content-Type: text/plain
... contents of bang.txt ...
--AaB03x--
 
以上表示数据name=bang以及一个文件,content.txt是文件名,… contents of bang.txt …是文件实体内容。分隔符—AaB03x是可以自定义的,写在HTTP头部里:
 
Content-type: multipart/form-data, boundary=AaB03x
 
每一个部分都有自己的头部,表明这部分的数据类型以及其他一些参数,例如文件名,普通字段的key。最后一个分隔符会多加两横,表示数据已经结束:—AaB03x—。
 
B.实现
接下来说说怎样构造Multipart里的数据,最简单的方式就是直接拼数据,要发送一个文件,就直接把文件所有内容读取出来,再按上述协议加上头部和分隔符,拼接好数据后扔给NSURLRequest的body就可以发送了,很简单。但这样做是不可用的,因为文件可能很大,这样拼数据把整个文件读进内存,很可能把内存撑爆了。
 
第二种方法是不把文件读出来,不在内存拼,而是新建一个临时文件,在这个文件上拼接数据,再把文件地址扔给NSURLRequest的bodyStream,这样上传的时候是分片读取这个文件,不会撑爆内存,但这样每次上传都需要新建个临时文件,对这个临时文件的管理也挺麻烦的。
 
第三种方法是构建自己的数据结构,只保存要上传的文件地址,边上传边拼数据,上传是分片的,拼数据也是分片的,拼到文件实体部分时直接从原来的文件分片读取。这方法没上述两种的问题,只是实现起来也没上述两种简单,AFNetworking就是实现这第三种方法,而且还更进一步,除了文件,还可以添加多个其他不同类型的数据,包括NSData,和InputStream。
 
AFNetworking 里 multipart 请求的使用方式是这样:
   
  1. AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; 
  2. NSDictionary *parameters = @{@"foo": @"bar"}; 
  3. NSURL *filePath = [NSURL fileURLWithPath:@"file://path/to/image.png"]; 
  4. [manager POST:@"http://example.com/resources.json" parameters:parameters constructingBodyWithBlock:^(id formData) { 
  5.     [formData appendPartWithFileURL:filePath name:@"image" error:nil]; 
  6. } success:^(AFHTTPRequestOperation *operation, id responseObject) { 
  7.     NSLog(@"Success: %@", responseObject); 
  8. } failure:^(AFHTTPRequestOperation *operation, NSError *error) { 
  9.     NSLog(@"Error: %@", error); 
  10. }]; 
这里通过constructingBodyWithBlock向使用者提供了一个AFStreamingMultipartFormData对象,调这个对象的几种append方法就可以添加不同类型的数据,包括FileURL/NSData/NSInputStream,AFStreamingMultipartFormData内部把这些append的数据转成不同类型的 AFHTTPBodyPart,添加到自定义的 AFMultipartBodyStream 里。最后把 AFMultipartBodyStream 赋给原来 NSMutableURLRequest的bodyStream。NSURLConnection 发送请求时会读取这个 bodyStream,在读取数据时会调用这个 bodyStream 的 -read:maxLength: 方法,AFMultipartBodyStream 重写了这个方法,不断读取之前 append进来的 AFHTTPBodyPart 数据直到读完。
 
AFHTTPBodyPart 封装了各部分数据的组装和读取,一个 AFHTTPBodyPart 就是一个数据块。实际上三种类型 (FileURL/NSData/NSInputStream) 的数据在 AFHTTPBodyPart 都转成 NSInputStream,读取数据时只需读这个 inputStream。inputStream 只保存了数据的实体,没有包括分隔符和头部,AFHTTPBodyPart 是边读取变拼接数据,用一个状态机确定现在数据读取到哪一部份,以及保存这个状态下已被读取的字节数,以此定位要读的数据位置,详见 AFHTTPBodyPart 的-read:maxLength:方法。
 
AFMultipartBodyStream封装了整个multipart数据的读取,主要是根据读取的位置确定现在要读哪一个AFHTTPBodyPart。AFStreamingMultipartFormData对外提供友好的append接口,并把构造好的AFMultipartBodyStream赋回给NSMutableURLRequest,关系大致如下图:
C.NSInputStream子类
NSURLRequest 的 setHTTPBodyStream 接受的是一个 NSInputStream* 参数,那我们要自定义inputStream的话,创建一个 NSInputStream 的子类传给它是不是就可以了?实际上不行,这样做后用NSURLRequest 发出请求会导致 crash,提示 [xx _scheduleInCFRunLoop:forMode:]: unrecognized selector。
 
这是因为NSURLRequest实际上接受的不是 NSInputStream 对象,而是 CoreFoundation 的 CFReadStreamRef 对象,因为 CFReadStreamRef 和 NSInputStream 是 toll-free bridged,可以自由转换,但CFReadStreamRef 会用到 CFStreamScheduleWithRunLoop 这个方法,当它调用到这个方法时,object-c 的 toll-free bridging 机制会调用 object-c 对象 NSInputStream 的相应函数,这里就调用到了_scheduleInCFRunLoop:forMode:,若不实现这个方法就会crash。详见这篇文章。
 
3.源码注释
   
  1. AFURLRequestSerialization.m 
【连接器专题】 EIA-364 系列标准的完整列表 EIA-364 系列标准在电子工业中具有重要的地位,为电子连接器和互连系统的测试和验证提供了统一的、可操作的流程和方法,有助于提高电子产品的质量和可靠性,促进了电子工业的发展 阅读详情

相关推荐

记一次springboot集成海康威视SDK过程

一开始没有接触过物联网这块,走了很多弯路,后面还是自己一点点摸索出来的。有个项目,需要对海康的门禁设备进行集成,后台统一管理设备,进行设备人脸数据的下发、删除等操作。3.我还接入了门禁设备的事件监听,门禁所有的事件都会上报到后台服务,这块代码有需要的可以找我。在linux系统中,sdk我使用的是绝对路径,把Linux版本的文件放到服务时,Acs文件夹下的 各个Manage都有现成的代码,可以根据自己的需要调用即可。路径也不要有中文,切记!2.sdk的存放路径不要有中文,不然会出现很多奇怪的问题。

huang_xiaoen的博客 2348

AFNetworking(二)AFNetworking对form-data请求体的处理

AFNetworking 发送 GET、POST 等请求时可以直接将参数按照字典结构传入,最终编码到 url 中或者是 body 实体中,同时也支持按照 multipart/form-data 格式,将多种不同的数据合入到 body 中进行发送,而这些就涉及到 AFNetworking 的请求序列化类,也就是 AFURLRequestSerialization。 AFURLRequestSeria...

weixin_34414196的博客 2424

2025浏览器指纹伪装终极指南:Playwright修改WebGL+时区+分辨率,小红书爬1000条零验证

2025年小红书的反爬已经进入“多维校验”时代,单纯修改某一个指纹维度已失效。本文方案的核心是“让所有特征都一致且合理”——WebGL+Canvas+时区+分辨率+UA+行为,形成一个完整的“真实用户画像”,让小红书的反爬系统无法区分是爬虫还是真人。这套方案不仅适用于小红书,也可迁移到知乎、抖音、跨境电商等其他高反爬平台,只需替换对应的指纹库和数据提取逻辑。记住:指纹伪装的本质不是“欺骗”,而是“模拟真实”,把每个细节都做到和人类一致,自然就能实现“零验证”爬取。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 3069

iOS之网络请求之AFN表单上传之form-data

表单上传呢一般是当要上传图片的时候用的网络请求方式。上传http post请求的表单格式是这样的Content-type: multipart/form-data, boundary=qwerdf --qwerdf content-disposition: form-data; name="field1" i will upload head! --qwerdf

Visars的博客 2万+

tkinter动态表格 - 实时更新数据(TkinterTable)

tkinter动态表格 - 实时更新数据(TkinterTable) 参考 [TkinterTable] Tkinter上的表格GUI】 https://github.com/dmnfarrell/tkintertable/wiki/Usage https://github.com/dmnfarrell/tkintertable/issues/47 python使用tkinter编写一个数据显示窗口(实时显示更新的数据) 首先安装TkinterTable,即pip install tki

qq_33934427的博客 1万+

机器人手眼标定快速精度验证方法

机器人手眼标定快速精度验证方法

laoli_的博客 1万+

图解HTTP三:HTTP 报文内的 HTTP 信息

3.1 HTTP 报文 用于 HTTP 协议交互的信息被称为 HTTP 报文。请求端(客户端)的 HTTP 报文叫做请求报文,响应端(服务器端)的叫做响应报文。 HTTP 报文的结构 3.2 请求报文及响应报文的结构 请求报文(上)和响应报文(下)的结构 请求行:包含用于请求的方法,请求 URI 和 HTTP 版本。 状态行:包含表明响应结果的状态码,原因短语和 HTTP 版本。 首部字段:包含表示请求和响应的各种条件和属性的各类首部。一般有 4

神薯片 2801

【Windows Server 2019】活动目录 (Active Directory) ——将计算机加入域和脱离域

博文介绍了如何将计算机加入AD域和脱离AD域,包括加入域,验证客户机加入到域后的信息,使用域账户用户在客户机上登录,使用本地账户用户在计算机上登录,脱离域。

VMware, Windows, Linux, Cisco, Container, Kubernetes, Kali 6169

【原】AFNetworking源码阅读(五)

【原】AFNetworking源码阅读(五) 本文转载请注明出处 —— polobymulberry-博客园 1. 前言 上一篇中提及到了Multipart Request的构建方法- [AFHTTPRequestSerializer multipartFormRequestWithMethod:URLString:parameters:constructingBodyWith...

weixin_30363817的博客 232

CDD数据库文件制作(二)——服务配置(0x27)

主要根据诊断调查表,针对0x27服务在CDD中的每一步配置给出详细介绍 1.会话切换配置 1.1.根据诊断调查表进行信息提取 1.2.子功能添加 1.2.1.Level1安全等级1创建 1.2.2.Level3安全等级3创建 1.2.3.安全等级名字查看与修改 1.3.会话切换信息提取(应用程序下) 1.4.会话转换配置(应用程序下) 1.5.会话切换信息提取(引导程序下) 1.6.会话转换配置(引导程序下) 2.安全等级配置信息提取 2.1.安全访问配置(level1) 2.2.安全访问配置(level2

LOVE135149的博客 2928

YOLOv11改进策略【小目标改进】| 添加专用于小目标的检测层 附YOLOv1~YOLOv11的检测头变化详解

在目标检测领域,小目标检测一直是一个具有挑战性的问题。算法以其高效快速的特点受到广泛关注,然而在面对小目标时,仍存在一些局限性。本文将介绍如何在中添加小目标检测层,以提高对小目标的检测能力。原始模型结构如下:详细内容参考:YOLOv11原始模型结构介绍 二、有效特征层对应的检测头类别 2.1 P3/8 - small检测头 原始模型中的对应的检测头主要用于检测相对较小的目标。其特征图大小相对较大,空间分辨率较高。 适合检测尺寸大概在到像素左右的目标。 2.2 P4/16 - medium检测头 这个检

Limiiiing的博客 8794

AFNetworking2.0源码解析<四>

续AFNetworking2.0源码解析,本篇来看看AFURLResponseSerialization做的事情。 结构 AFURLResponseSerialization负责解析网络返回数据,检查数据是否合法,把NSData数据转成相应的对象,内置的转换器有json,xml,plist,image,用户可以很方便地继承基类AFHTTPResponseSerializer去解析更多的

sunyazhou13的专栏 495

【技能】伪真openclaw主动式智能体—告别‘巨婴’AI工具人:体验主动智能体的魅力

摘要: 传统AI常因被动执行、缺乏闭环而令人抓狂。Proactivity主动执行能力将AI从"指令跟随者"升级为"主动合伙人",具备预判需求、自动推进、断聊恢复、问题自解等能力。其核心原理在于建立AI专属工作体系(持久化内存、动态任务层、临时缓存层、归档复盘层),通过7步闭环(感知触发→状态恢复→边界校验→方案探索→动作决策→执行落地→状态留存)确保安全高效。

海兰 207

AFNetworking2.0源码解析<一>

(via:bang's blog) 最近看AFNetworking2的源码,学习这个知名网络框架的实现,顺便梳理写下文章。AFNetworking的代码还在不断更新中,我看的是AFNetworking2.3.1。 本篇先看看AFURLConnectionOperation,AFURLConnectionOperation继承自NSOperation,是一个封装好的任务...

Bnbn123111的博客 227

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

AFNetworking (3.1.0) 源码解析 <一>

首先说一下AFNetworking的github地址:GitHub - AFNetworking/AFNetworking: A delightful networking framework for iOS 最近抓时间研究了一下AFNetworking,目前版本是3.1.0,我通过CocoaPods导入的AFNetworking,导入后目录如下 使用CocoaPods导入后可以看到...

217

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

上一篇: AFNetworking2.0源码解析
下一篇: AFNetworking源码解析<三>
focusjava
博客等级 码龄14年 127粉丝 528原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值