在MeToo的研发过程中,部分模块需要使用http请求向服务器同时传输图片和一些附属信息。由于图片使用NSDATA格式传输,附属信息使用JSON格式传输,而消息的body只能支持其中一种格式,因此在只要传输JSON信息的时候,使用UTF8编码传输;在需要同时传输图片和附属信息时,将图片以二进制格式放在body里,附属信息的JSON放在header里,如下所示:
[[SVHTTPClient sharedClientWithIdentifier:@"upload"] setValue:_delegate.userID forHTTPHeaderField:@"userid"];
。。。。。。
[[SVHTTPClient sharedClientWithIdentifier:@"upload"]POST:POSTVOTE_SERVLET parameters:[NSDictionary dictionaryWithObjectsAndKeys:
imageData, @"image",
nil]
completion:^(id response, NSHTTPURLResponse *urlResponse, NSError *error) { …… }];
但这里有个问题,在httpheader中设置的编码格式只对body起作用,header本身只支持ascii的文本,如果将中文放在header中(即使用JSON包装也一样),传到服务器端后服务器解析不出来,从而报JSON格式错误。
解决方法是,对汉字进行UTF编码,得到类似16进制的文本串,在作为JSON的数据传输。Objectivec中的代码为:
NSString *str = @"中国1美国a23";
NSString *unicodeStr = [str stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSLog(@"%@", unicodeStr);
输出结果为:
%E4%B8%AD%E5%9B%BD1%E7%BE%8E%E5%9B%BDa23
该结果有两点问题:
1, oc只能用”%”来标记一个字节的16进制数,而java的写法是”\x”
2, 对于latin字符,如示例中的1,2,3,a,oc不会对其进行编码,而如果用JAVA的UTF8编码会将”1”编码成”\x31”的形式
因此在还原时,不能对oc编码后的结果直接还原,而需要先将%E4替换为\xE4的形式(其实是转成0XE4形式),对于没有替换的latin字符则直接读入不做任何处理。
服务器端的java代码如下:
public static String hex2Str(String str) throws UnsupportedEncodingException {
byte[] byteArr = new byte[1024];
int num=0;
for (int i = 0; i < str.length();) {
if (str.charAt(i)=='%'){
Integer hexInt = Integer.decode("0x" + str.charAt(i+1) + str.charAt(i+2));
byteArr[num] = hexInt.byteValue();
i+=3;
num++;
}else{
byteArr[num] = (byte)str.charAt(i);
num++;
i++;
}
}
byteArr[num] = '\0';
return new String(byteArr, "UTF-8");
}