一个银行的项目要求POST请求的时候参数以二进制流的形式传输,也就是将字典转换为json字符串,然后把字符串转换为二进制流的形式进行传输
于是稍作修改,问题解决
接下来从以下几个方面说明一下:
1.更改Content-Type为支持流的形式
AFN默认使用的Content-Type是 application/x-www-form-urlencoded,如果我们正常的以key-value的形式发出去这个是没有问题的,并且AFN也会对我们的参数(NSArray、NSDictionary、NSSet)进行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