赞
踩
https://blog.csdn.net/breeze048/article/details/79426819
相关网址:https://ai.qq.com/doc/auth.shtml
如腾讯Ai给出的示例,其中app_id, time_stamp, nonce_str, sign为发起对腾讯Ai各种Api都需要加入到post请求的数据。而key1,key2则根据不同Api会有不同。如下面的OCR通用文字识别Api
图中唯一不同于示例的是把key1,key2换成了image,即待识别图片的base64编码数据。
实际上也是如此,对待不同的Api请求,只需要修改key1,key2成对应的键值对即可。
app_id为应用标识,到腾讯Ai平台申请项目就会得到app_id,和app_key。app_key在后续的鉴权生成时会用到。
申请项目获得密钥的接入文档https://ai.qq.com/doc/index.shtml
秒级时间戳
实际上就可以使用系统时间(毫秒)/1000得到需要的值。如:
String time_stamp = System.currentTimeMillis() / 1000 + "";
随机字符串
- public static String getRandomString(int length) {
- String base = "abcdefghijklmnopqrstuvwxyz0123456789";
- Random random = new Random();
- StringBuffer sb = new StringBuffer();
- for (int i = 0; i < length; i++) {
- int number = random.nextInt(base.length());
- sb.append(base.charAt(number));
- }
- return sb.toString();
- }
利用随机数字去生成即可。
base64的编码工具类在网上到处都能找得到,这里就不贴算法了,比较长
这个部分的流程主要是将图片以字节数据读入,然后再进行base64编码
- byte[] imageData = FileUtil.readFileByBytes(file);
- String img64 = Base64Util.encode(imageData);
先看腾讯给出的说明文档:
1.字典升序排序而且还是键值对,可以想到使用java中的TreeMap去处理存储这些数据最为合适
具体签名部分代码如下:
- private String generateAppSign() throws UnsupportedEncodingException {
- Set<String> keySet = mParams.keySet();
- StringBuilder sb = new StringBuilder();
- Iterator<String> iterator = keySet.iterator();
- while (iterator.hasNext()) {
- String key = iterator.next();
- String value = mParams.get(key);
- sb.append("&").append(key).append("=").append(URLEncoder.encode(value, "UTF-8"));
- }
- sb.deleteCharAt(0);
- sb.append("&app_key=").append(TencentAIConstants.APP_KEY_AI);
- String sign = MD5.getMD5(sb.toString());
- return sign;
- }
代码中的mParams参数就是一个TreeMap对象,存储着除sign之外的其他键值对,利用这些键值对计算生成sign字段。
发起请求这里使用okhttp,不使用HttpClient原因是安卓现在不支持使用HttpClient了,使用okhttp使用范围更广一点而且也很方便实现。主要代码:
- MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM);
- Iterator<String> iterator = mParams.keySet().iterator();
- while (iterator.hasNext()) {
- String key = iterator.next();
- String value = mParams.get(key);
- builder.addFormDataPart(key, value);
- }
- RequestBody requestBody = builder.build();
- Request request = new Request.Builder().header("Content-Type", "application/x-www-form-urlencoded")
- .url(url)
- .post(requestBody)
- .build();
- OkHttpClient okHttpClient = new OkHttpClient();
- Response response = okHttpClient.newCall(request).execute();
- if (!response.isSuccessful()){
- return ERROR;
- }
- return response.body().string();
对于这种部分参数一致,部分参数不同,且逻辑一致的需求使用Builder模式很合适。将上述列出的代码使用builder模式写一个通用的类用于各类请求再合适不过了。代码如下:
- public class AiRequestBean {
-
- public static final String ERROR = "error";
- private TreeMap<String, String> mParams;
-
- private AiRequestBean() {
- mParams = new TreeMap<>();
- //时间戳
- String time_stamp = System.currentTimeMillis() / 1000 + "";
- //随机字符串
- String nonce_str = TencentAIParamsHelper.getRandomString(10);
- //appId
- String app_id = String.valueOf(TencentAIConstants.APP_ID_AI);
- //将通用参数设置进map中
- mParams.put("app_id", app_id);
- mParams.put("nonce_str", nonce_str);
- mParams.put("time_stamp", time_stamp);
- }
-
- /**
- * TreeMap生成鉴权信息
- */
- private String generateAppSign() throws UnsupportedEncodingException {
- Set<String> keySet = mParams.keySet();
- StringBuilder sb = new StringBuilder();
- Iterator<String> iterator = keySet.iterator();
- while (iterator.hasNext()) {
- String key = iterator.next();
- String value = mParams.get(key);
- sb.append("&").append(key).append("=").append(URLEncoder.encode(value, "UTF-8"));
- }
- sb.deleteCharAt(0);
- sb.append("&app_key=").append(TencentAIConstants.APP_KEY_AI);
- String sign = MD5.getMD5(sb.toString());
- return sign;
- }
-
- //发起请求
- public String request(String url) throws IOException {
- //生成签名加入到参数列表中
- String sign = generateAppSign();
- mParams.put("sign", sign);
- //使用okhttp发起请求
- MultipartBody.Builder builder = new MultipartBody.Builder().setType(MultipartBody.FORM);
- Iterator<String> iterator = mParams.keySet().iterator();
- while (iterator.hasNext()) {
- String key = iterator.next();
- String value = mParams.get(key);
- builder.addFormDataPart(key, value);
- }
- RequestBody requestBody = builder.build();
- Request request = new Request.Builder().header("Content-Type", "application/x-www-form-urlencoded")
- .url(url)
- .post(requestBody)
- .build();
- OkHttpClient okHttpClient = new OkHttpClient();
- Response response = okHttpClient.newCall(request).execute();
- if (!response.isSuccessful()){
- return ERROR;
- }
- return response.body().string();
- }
-
- public static class Builder {
- private AiRequestBean targetBean;
-
- public Builder() {
- targetBean = new AiRequestBean();
- }
-
- public AiRequestBean build() {
- return targetBean;
- }
-
- public Builder addParam(String key, String value) {
- targetBean.mParams.put(key, value);
- return this;
- }
- }
- }
使用方法也很简单,比如以通用ocr为例,通用ocr文字识别中不同的参数为image,对应的Api为”https://api.ai.qq.com/fcgi-bin/ocr/ocr_generalocr”
- public static final String URL4GENERALOCR = "https://api.ai.qq.com/fcgi-bin/ocr/ocr_generalocr";
- //通用ocr文字识别请求
- public String getGeneralOcrResult(File file) throws Exception {
- byte[] imageData = FileUtil.readFileByBytes(file);
- //准备好图片base64数据
- String img64 = Base64Util.encode(imageData);
- String jsonResult = new AiRequestBean.Builder().addParam("image", img64).build().request(TencentAIConstants.URL4GENERALOCR);
- return jsonResult;
- }
可以看到还是很方便使用的。
Demo代码链接:http://download.csdn.net/download/breeze048/10267182
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。