封装API方式请求
做的时候遇到:oc提供的base64二进制方法,base64之后有\r,\n这两个字符,需要移除,移除之后urlEncode
1.请求token
- (void)authWithAPIKey:(NSString *)strApi secretKey:(NSString *)strSecret {
if ([self checkLocalTokenValidWithApiKey:strApi secretKey:strSecret])
{
//本地token有效,并且已经复制self.strToken,重发之前因为token失败的任务
[self handleGetStokenSuccess];
return;
}
NSString *strUrl = @"https://aip.baidubce.com/oauth/2.0/token";
NSDictionary *dicParam = @{@"grant_type":@"client_credentials",
@"client_id":strApi,
@"client_secret":strSecret};
[self requestWithParams:dicParam url:strUrl completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (error)
{
NSLog(@"request token error:\n%@",error);
}
else
{
if (data)
{
NSDictionary *dicRe = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
NSString *token = [dicRe objectForKey:@"access_token"];
//本地token更新
if (token)
{
self.strToken = token;
//这里定义了几个常量用于存储本地token相关信息
NSDictionary *dicToken = @{USERDEFAULT_OCR_TOKEN:token,USERDEFAULT_OCR_TIME:[NSString stringWithFormat:@"%f",[NSDate date].timeIntervalSince1970],USERDEFAULT_OCR_API:strApi,USERDEFAULT_OCR_SECRET:strSecret};
[[NSUserDefaults standardUserDefaults] setObject:dicToken forKey:USERDEFAULT_OCR];
[self handleGetStokenSuccess];
}
else
{
NSString *error = dicRe[@"error"];
NSLog(@"request token error:\n%@",error);
}
}
}
}];
}
2.发起请求
/**
图像二进制识别文字
@param imageData 1
@param successHandler 1
@param failHandler 1
*/
- (void)detectTextFromImageData:(NSData *)imageData
successHandler: (void (^)(id result))successHandler
failHandler: (void (^)(NSError* err))failHandler
{
if (!self.strToken.length)
{
//未获取百度token
_bOcrWaiting = YES;
//添加等待任务
[self addWaiting:imageData successHandler:successHandler failHandler:failHandler];
[self authWithAPIKey:BD_OCR_API_KEY secretKey:BD_OCR_SECRET_KEY];
return;
}
if (imageData == nil)
{
//data为空
NSLog(@"ocr data is nil");
[self handleFaileHandle:failHandler errorCode:-1 errMessage:@"ocr data is nil"];
return;
}
//将data base64
NSString *strBase64 = [imageData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
//删除base64中的换行符
strBase64 = [strBase64 stringByReplacingOccurrencesOfString:@"\n" withString:@""];
strBase64 = [strBase64 stringByReplacingOccurrencesOfString:@"\r" withString:@""];
//配置参数
NSMutableDictionary *params = [[NSMutableDictionary alloc] init];
//是否返回识别结果中每一行的置信度
[params setObject:@"false" forKey:@"probability"];
//是否检测语言,默认不检测。
[params setObject:@"1" forKey:@"detect_language"];
//是否检测图像朝向,默认不检测,false/true
[params setObject:@"false" forKey:@"detect_direction"];
//鉴权token
[params setObject:self.strToken forKey:@"token"];
//识别语言类型,默认为CHN_ENG.CHN_ENG:中英文混合; ENG:英文;POR:葡萄牙语; FRE:法语;GER:德语; ITA:意大利语;SPA:西班牙语;RUS:俄语;JAP:日语;KOR:韩语
[params setObject:@"CHN_ENG" forKey:@"language_type"];
//image数据,二进制文件进行base64编码后,最短边至少15px,最长边最大4096px,base64编码后大小不超过4M
[params setObject:strBase64 forKey:@"image"];
[params setObject:self.strToken forKey:@"access_token"];
NSString *strUrl = @"https://aip.baidubce.com/rest/2.0/ocr/v1/general_basic";
[self requestWithParams:params
url:strUrl
completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error)
{
if (error)
{
//网络请求出错
NSLog(@"ocr error:\n%@",error);
[self handleFaileHandle:failHandler errorCode:-1 errMessage:error.description];
}
else
{
if (data)
{
NSString *strD = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(@"ocr strResult:\n%@",strD);
NSDictionary *dicResult = [NSJSONSerialization JSONObjectWithData:[strD dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingMutableLeaves error:nil];
[strD release];
if (dicResult[@"words_result"])
{
//识别成功
if (successHandler != nil)
{
successHandler(dicResult);
}
}
else
{
//识别出错
NSInteger err_code = [dicResult[@"error_code"] integerValue];
if (err_code == 100 ||//无效的access_token参数
err_code == 110 ||//access_token无效
err_code == 111)//access token过期
{
_bOcrWaiting = YES;
//移出无效的token
self.strToken = @"";
[[NSUserDefaults standardUserDefaults] removeObjectForKey:USERDEFAULT_OCR];
//添加任务到等待列表
[self addWaiting:imageData successHandler:successHandler failHandler:failHandler];
//重新获取token
[self authWithAPIKey:BD_OCR_API_KEY secretKey:BD_OCR_SECRET_KEY];
}
else if (err_code == 216201 ||
err_code == 216202)
{
[self handleFaileHandle:failHandler errorCode:err_code errMessage:@"不支持的图片"];
}
else
{
NSString *err_msg = dicResult[@"error_msg"];
[self handleFaileHandle:failHandler errorCode:err_code errMessage:err_msg];
}
}
NSLog(@"ocr dicResult:\n%@",dicResult);
}
else
{
//一个报错处理
[self handleFaileHandle:failHandler errorCode:-1 errMessage:@"ocr has no result data"];
NSLog(@"ocr has no result data");
}
}
}];
[params release];
}
3.自己写的请求方法
/**
post网络请求
@param params 参数
@param strUrl url
@param completionHandler 1
*/
- (void)requestWithParams:(NSDictionary *)params url:(NSString *)strUrl completionHandler:(void (^)(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error))completionHandler{
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:strUrl]];
request.HTTPMethod = @"POST";
request.HTTPBody = [[self transformDictionaryToString:params] dataUsingEncoding:NSUTF8StringEncoding];
NSURLSessionDataTask *dataTask = [self.pUrlSession dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error)
{
if (completionHandler) completionHandler(data,response,error);
}];
[dataTask resume];
}
4.网络请求相关的两个工具方法
/**
字典转字符串
@param dict 1
@return 1
*/
- (NSString *)transformDictionaryToString:(NSDictionary *)dict {
NSMutableString *strParams = [NSMutableString string];
//遍历并拼接
for (NSString *key in dict.allKeys)
{
[strParams appendFormat:@"%@=%@&",[self urlEncodeString:key],[self urlEncodeString:[dict objectForKey:key]]];
}
NSString *str = [strParams substringToIndex:strParams.length - 1];
return str;
}
/**
urlEncode,来源AFNetworking -> AFURLRequestSerialization.m NSString * AFPercentEscapedStringFromString(NSString *string){}
@param string 1
@return 1
*/
- (NSString *)urlEncodeString:(NSString *)string {
static NSString * const kAFCharactersGeneralDelimitersToEncode = @":#[]@"; // does not include "?" or "/" due to RFC 3986 - Section 3.4
static NSString * const kAFCharactersSubDelimitersToEncode = @"!$&'()*+,;=";
NSMutableCharacterSet * allowedCharacterSet = [[NSCharacterSet URLQueryAllowedCharacterSet] mutableCopy];
[allowedCharacterSet removeCharactersInString:[kAFCharactersGeneralDelimitersToEncode stringByAppendingString:kAFCharactersSubDelimitersToEncode]];
// FIXME: https://github.com/AFNetworking/AFNetworking/pull/3028
// return [string stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacterSet];
static NSUInteger const batchSize = 50;
NSUInteger index = 0;
NSMutableString *escaped = [@"".mutableCopy autorelease];
while (index < string.length) {
@autoreleasepool {
NSUInteger length = MIN(string.length - index, batchSize);
NSRange range = NSMakeRange(index, length);
// To avoid breaking up character sequences such as
range = [string rangeOfComposedCharacterSequencesForRange:range];
NSString *substring = [string substringWithRange:range];
NSString *encoded = [substring stringByAddingPercentEncodingWithAllowedCharacters:allowedCharacterSet];
[escaped appendString:encoded];
index += range.length;
}
}
[allowedCharacterSet release];
return escaped;
}