项目开发中,我们往往会遇到一些特殊的需求,下面我就分享下我最近遇到的一个需求:
1、用户进行实名认证时将身份证的正反面照拍照上传(此功能无特别之处,合理也没难度)
2、对上传的图片进行解析,提取出页面需要展示的字段(问题应该不大)
自我感觉良好后,就着手干了,下面是我的实现过程:
首先到百度文字识别注册用户,生成你的ID,KEY,SECRET_KEY,地址:https://cloud.baidu.com/doc/OCR/s/rk3h7xzck
创建一个工具类:
public class BaiduApiUtil { //设置APPID/AK/SK private static String APP_ID = "16516516"; private static String API_KEY ="XAxM8sp351651kv2IB"; private static String SECRET_KEY = "tcENajuNu5116530368N9zIYGB"; /** * 读取身份证正面照片信息 * */ public static JSONObject getFrontPicture(){ // 初始化一个AipOcr AipOcr client = new AipOcr(APP_ID, API_KEY, SECRET_KEY); // 可选:设置网络连接参数 client.setConnectionTimeoutInMillis(2000); client.setSocketTimeoutInMillis(60000); // 传入可选参数调用接口 HashMap<String, String> options = new HashMap<String, String>(); // 是否检测朝向 options.put("detect_direction", "false"); // 是否检测风险 options.put("detect_risk", "false"); //正反面front /back String idCardSide = "front"; // 参数为本地图片路径 String photoPath = "E://img//****.jpg"; try { JSONObject res = client.idcard(photoPath, idCardSide, options); System.out.println(res.toString(2)); if (res != null) { JSONObject wordsResult = res.getJSONObject("words_result"); return wordsResult; } else { return null; } }catch (JSONException e){ e.printStackTrace(); } return null; }
}
当你兴致勃勃搞完准备接上业务逻辑时,发现这个方法有个很大的限制,它只能只能真的只能解析本地图片,当你配合阿里OSS用时,发现文件存储服务器返回的文件地址是无法直接解析的,这个就很痛苦了。。。。
至此,这个方法是行不通了,我换了个实现方式,现将前端上传的图片存到本地进行图片解析及上传阿里OSS,将上个方法稍作修改
public class BaiduApiUtil(String photoPath) { //设置APPID/AK/SK private static String APP_ID = "16516516"; private static String API_KEY ="XAxM8sp351651kv2IB"; private static String SECRET_KEY = "tcENajuNu5116530368N9zIYGB"; /** * 读取身份证正面照片信息 * */ public static JSONObject getFrontPicture(){ // 初始化一个AipOcr AipOcr client = new AipOcr(APP_ID, API_KEY, SECRET_KEY); // 可选:设置网络连接参数 client.setConnectionTimeoutInMillis(2000); client.setSocketTimeoutInMillis(60000); // 传入可选参数调用接口 HashMap<String, String> options = new HashMap<String, String>(); // 是否检测朝向 options.put("detect_direction", "false"); // 是否检测风险 options.put("detect_risk", "false"); //正反面front /back String idCardSide = "front"; // 参数为本地图片路径 try { JSONObject res = client.idcard(photoPath, idCardSide, options); System.out.println(res.toString(2)); if (res != null) { JSONObject wordsResult = res.getJSONObject("words_result"); return wordsResult; } else { return null; } }catch (JSONException e){ e.printStackTrace(); } return null; }
}
解析及上传:
@Override public String uploadPicture(MultipartFile file, String frontOrBack) { Map<String, Object> value = new HashMap<String, Object>(); try { String url = upImgService.updateHead(file); System.out.println(url); value.put("url", url); value.put("code", 0); value.put("msg", "图片上传成功"); } catch (Exception e) { value.put("code", 2000); value.put("msg", "图片上传失败"); } if (file.isEmpty()){ return "该文件是空的"; } String filename = file.getOriginalFilename(); String suffixName = filename.substring(filename.lastIndexOf(".")); String filePath = "F://home//imgs//"; filename = UUID.randomUUID() + suffixName; File dest = new File(filePath + filename); if (!dest.getParentFile().exists()) { dest.getParentFile().mkdirs(); } try { file.transferTo(dest); } catch (IOException e) { e.printStackTrace(); } String imgPath = filePath + filename; System.out.println(imgPath); if (frontOrBack.equals("front")){ org.json.JSONObject frontPicture = BaiduApiUtil.getFrontPicture(imgPath); value.put("name", frontPicture.getJSONObject("姓名").get("words")); value.put("sex", frontPicture.getJSONObject("性别").get("words")); value.put("number", frontPicture.getJSONObject("公民身份号码").get("words")); return JSONObject.toJSONString(value); }else if (frontOrBack.equals("back")){ org.json.JSONObject backPicture = BaiduApiUtil.getBackPicture(imgPath); value.put("usefulTime", backPicture.getJSONObject("失效日期").get("words")); return JSONObject.toJSONString(value); } return ""; }
Controller直接调用该方法即可,postman跑下接口,发现并没有问题,到此,身份图片上传+信息解析完美实现。
当然,还是希望阿里哪天能实现下图片上传+信息解析的功能。
Ps:如果文件上传量大的话,可以采用创建临时目录来实现,毕竟用完就可以删掉,也不必担心服务器内存问题了。