iOS之AFNetworking在POST时以二进制形式传输

6 篇文章 0 订阅
3 篇文章 0 订阅

一个银行的项目要求POST请求的时候参数以二进制流的形式传输,也就是将字典转换为json字符串,然后把字符串转换为二进制流的形式进行传输


于是稍作修改,问题解决

 

接下来从以下几个方面说明一下:


1.更改Content-Type为支持流的形式


AFN默认使用的Content-Type application/x-www-form-urlencoded,如果我们正常的以key-value的形式发出去这个是没有问题的,并且AFN也会对我们的参数(NSArrayNSDictionaryNSSet)进行urlencoded.具体操作如下

 

 NSArray * AFQueryStringPairsFromKeyAndValue(NSString *key, id value) {
 NSMutableArray *mutableQueryStringComponents = [NSMutableArray array];
 
 NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"description" ascending:YES selector:@selector(compare:)];
 
 if ([value isKindOfClass:[NSDictionary class]]) {
 NSDictionary *dictionary = value;
 // Sort dictionary keys to ensure consistent ordering in query string, which is important when deserializing potentially ambiguous sequences, such as an array of dictionaries
 for (id nestedKey in [dictionary.allKeys sortedArrayUsingDescriptors:@[ sortDescriptor ]]) {
 id nestedValue = dictionary[nestedKey];
 if (nestedValue) {
 [mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue((key ? [NSString stringWithFormat:@"%@[%@]", key, nestedKey] : nestedKey), nestedValue)];
 }
 }
 } else if ([value isKindOfClass:[NSArray class]]) {
 NSArray *array = value;
 for (id nestedValue in array) {
 [mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue([NSString stringWithFormat:@"%@[]", key], nestedValue)];
 }
 } else if ([value isKindOfClass:[NSSet class]]) {
 NSSet *set = value;
 for (id obj in [set sortedArrayUsingDescriptors:@[ sortDescriptor ]]) {
 [mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue(key, obj)];
 }
 } else {
 [mutableQueryStringComponents addObject:[[AFQueryStringPair alloc] initWithField:key value:value]];
 }
 
 return mutableQueryStringComponents;
 }

 

 NSArray * AFQueryStringPairsFromKeyAndValue(NSString *key, id value) {
 NSMutableArray *mutableQueryStringComponents = [NSMutableArray array];
 
 NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"description" ascending:YES selector:@selector(compare:)];
 
 if ([value isKindOfClass:[NSDictionary class]]) {
 NSDictionary *dictionary = value;
 // Sort dictionary keys to ensure consistent ordering in query string, which is important when deserializing potentially ambiguous sequences, such as an array of dictionaries
 for (id nestedKey in [dictionary.allKeys sortedArrayUsingDescriptors:@[ sortDescriptor ]]) {
 id nestedValue = dictionary[nestedKey];
 if (nestedValue) {
 [mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue((key ? [NSString stringWithFormat:@"%@[%@]", key, nestedKey] : nestedKey), nestedValue)];
 }
 }
 } else if ([value isKindOfClass:[NSArray class]]) {
 NSArray *array = value;
 for (id nestedValue in array) {
 [mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue([NSString stringWithFormat:@"%@[]", key], nestedValue)];
 }
 } else if ([value isKindOfClass:[NSSet class]]) {
 NSSet *set = value;
 for (id obj in [set sortedArrayUsingDescriptors:@[ sortDescriptor ]]) {
 [mutableQueryStringComponents addObjectsFromArray:AFQueryStringPairsFromKeyAndValue(key, obj)];
 }
 } else {
 [mutableQueryStringComponents addObject:[[AFQueryStringPair alloc] initWithField:key value:value]];
 }
 
 return mutableQueryStringComponents;
 }

 但是想要以流的形式发出去就要更改type .

将其改为 application/octet-stream就可以了

具体的修改的位置为:

找到 AFURLRequestSerialization.m文件,然后定位到 521行,相信就可以看到

if (![mutableRequest valueForHTTPHeaderField:@"Content-Type"]) {
    [mutableRequest setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
}


然后修改为

if (![mutableRequest valueForHTTPHeaderField:@"Content-Type"]) {
    [mutableRequest setValue:@"application/octet-stream" forHTTPHeaderField:@"Content-Type"];
}

这样就设置了请求体的内容格式就会支持二进制流


2.去掉AFN的自动urlencoded

如上所说,AFNetworking默认的为 application/x-www-form-urlencoded,会自动的为每个参数进行urlencoded,并且服务器会自动的进行反编码。但是当我们更改为支持二进制流的话,就要将AFNetworking的这个功能给屏蔽掉,要不然服务器收到的都是编码之后的urlencoded编码格式的,并且不会自动的反编码。

如何屏蔽?

同样的文件中,496行处可以看到如下代码

switch (self.queryStringSerializationStyle) {
    case AFHTTPRequestQueryStringDefaultStyle:
        query = AFQueryStringFromParameters(parameters);
        break;
}


代码中AFQueryStringFromParameters就是进行urlencoded的代码

将其删除或者屏蔽掉改为

query = parameters;

这样就跳过了转码


3.POST请求的参数传入json格式的字符串

当然如果想要加密,就将加密之后的字符串当做参数就可以了


4.补充

1>关于urlencode 的知识可以看一下 

 RFC3986之URL编码与解码 http://blog.csdn.net/qq_32010299/article/details/51790407

2> Content-type 大全

http://tool.oschina.net/commons




评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值