個(gè)人網(wǎng)站頁面設(shè)計(jì)需要那些步驟seo教學(xué)平臺
目錄
一、?注冊華為云賬號開通識別駕駛證、行駛證服務(wù)
二、編寫配置文件
? ? ? ? 2.1、配置秘鑰
? ? ? ? 2.2、?編寫配置工具類
三、接口測試
? ? ? ? 3.1、測試接口
? ? ? ? 3.2、結(jié)果
?四、實(shí)際工作中遇到的問題
? ? ? ? 4.1、前端傳值問題
? ? ? ? 4.2、后端獲取數(shù)據(jù)問題
????????4.3、使用openfeign調(diào)用接口報(bào)錯(cuò)
????????4.3、前端顯示問題
hello大家好,好久沒寫博客了,你們找到工作了嗎?博主在去年11月成功找到工作,到現(xiàn)在上班大半年了,最近需求用到華為云OCR文字識別,這里就詳細(xì)記錄一下!
一、?注冊華為云賬號開通識別駕駛證、行駛證服務(wù)
華為云官網(wǎng):特惠專區(qū)_云服務(wù)器_云主機(jī)_企業(yè)上云-華為云
?如上圖所示,華為云還有很多文字識別服務(wù),這個(gè)看個(gè)人需求了解即可。
?開放api接口地址體驗(yàn):https://console.huaweicloud.com/apiexplorer/#/openapi/OCR/debug?api=RecognizeDriverLicense
二、編寫配置文件
? ? ? ? 2.1、配置秘鑰
ocr:projectId: xxxxxxxxxxxxxx // 項(xiàng)目id:華為云個(gè)人憑證獲取area: cn-north-4????????// 區(qū)域:北京4區(qū),目前好像只有北京4區(qū)支持這兩個(gè)證件的識別服務(wù)ak: xxxxxxxxxxxxx????????//AK:華為云個(gè)人憑證獲取sk: xxxxxxxxxxxxx????????//SK:華為云個(gè)人憑證獲取
? ? ? ? 2.2、?編寫配置工具類
@Component
public class OcrUtil {private static final Logger log = LoggerFactory.getLogger(HttpUtils.class);@Value("${ocr.projectId}")private String projectId;@Value("${ocr.area}")private String area;@Value("${ocr.ak}")private String AK;@Value("${ocr.sk}")private String SK;private static CloseableHttpClient httpClient;static {PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();cm.setMaxTotal(100);cm.setDefaultMaxPerRoute(20);cm.setDefaultMaxPerRoute(50);httpClient = HttpClients.custom().setConnectionManager(cm).build();}public String getTokenByAKSK (){String url = "https://iam."+area+".myhuaweicloud.com/v3/auth/tokens";Map<String,String> p1 = new HashMap<>();Map<String,Object> p2 = new HashMap<>();Map<String,Object> p3 = new HashMap<>();Map<String,Object> p4 = new HashMap<>();Map<String,Object> p5 = new HashMap<>();Map<String,Object> p6 = new HashMap<>();Map<String,Object> p7 = new HashMap<>();Map<String,Object> p8 = new HashMap<>();p1.put("key",AK);p2.put("key",SK);p3.put("access",p1);p3.put("secret",p2);p4.put("hw_ak_sk",p3);String[] str = new String[1];str[0] = "hw_ak_sk";p4.put("methods",str);p5.put("identity",p4);p6.put("name",area);p7.put("project",p6);p5.put("scope",p7);p8.put("auth",p5);String result = postJson(url, JSON.toJSONString(p8));return result;}public static String postJson(String url, String jsonString) {CloseableHttpResponse response = null;String result = "";try {HttpPost httpPost = new HttpPost(url);RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(30000).setConnectionRequestTimeout(30000).setSocketTimeout(30000).build();httpPost.setConfig(requestConfig);httpPost.setConfig(requestConfig);httpPost.addHeader("Content-type", "application/json; charset=utf-8");httpPost.setHeader("Accept", "application/json");httpPost.setEntity(new StringEntity(jsonString, StandardCharsets.UTF_8));response = httpClient.execute(httpPost);Header[] h = response.getAllHeaders();for(Header header : h){if(header.getName().equals("X-Subject-Token")){result = header.getValue();}}} catch (IOException e) {log.error("調(diào)用HttpUtils.Post IOException, url=" + url + ",param=" + jsonString, e);} finally {try {if (response != null) {response.close();}} catch (IOException e) {log.error("調(diào)用HttpUtils.Post IOException, url=" + url + ",param=" + jsonString, e);}}return result;}public static Result postJson(String url, String token, String jsonString) {CloseableHttpResponse response = null;BufferedReader in;String result = "";boolean err = false;try {HttpPost httpPost = new HttpPost(url);RequestConfig requestConfig = RequestConfig.custom().setConnectTimeout(30000).setConnectionRequestTimeout(30000).setSocketTimeout(30000).build();httpPost.setConfig(requestConfig);httpPost.setConfig(requestConfig);httpPost.addHeader("Content-type", "application/json; charset=utf-8");httpPost.setHeader("Accept", "application/json");httpPost.setHeader("X-Auth-Token", token);httpPost.setEntity(new StringEntity(jsonString, StandardCharsets.UTF_8));response = httpClient.execute(httpPost);in = new BufferedReader(new InputStreamReader(response.getEntity().getContent()));StringBuilder sb = new StringBuilder();String line;String NL = System.getProperty("line.separator");while ((line = in.readLine()) != null) {sb.append(line).append(NL);}in.close();result = sb.toString();err = response.getStatusLine().getStatusCode() == 400;} catch (IOException e) {log.error("調(diào)用HttpUtils.Post IOException, url=" + url + ",param=" + jsonString, e);} finally {try {if (response != null) {response.close();}} catch (IOException e) {log.error("調(diào)用HttpUtils.Post IOException, url=" + url + ",param=" + jsonString, e);}}if (err) {return Result.error().data("data", result);} else {return Result.ok().data("data", result);}}/*** 功能描述:* 華為云駕駛證識別* @Param: [token, imageUrl]* @Return: com.ruoyi.phaseone.common.utils.R* @Author: Mr.Huang* @Date: 2023/8/10 10:21**/public Result driverLicense(String token, String imageUrl) {String url = "https://ocr."+area+".myhuaweicloud.com/v2/"+projectId+"/ocr/driver-license";Map<String, Object> p = new HashMap<>();// url:圖片地址 image:圖片的base64數(shù)據(jù) 兩個(gè)參數(shù)二選一,詳情見官網(wǎng)APIp.put("url", imageUrl);p.put("side", "front");log.info("ocr駕駛證識別請求路徑:{},請求參數(shù):{}",url,p);return postJson(url, token, JSON.toJSONString(p));}/*** 功能描述:* 華為云行駛證識別* @Param: [token, imageUrl]* @Return: com.sy.milkteasyservice.response.Result* @Author: Mr.Huang* @Date: 2023/8/14 10:52**/public Result vehicleLicense(String token, String imageUrl) {String url = "https://ocr."+area+".myhuaweicloud.com/v2/"+projectId+"/ocr/vehicle-license";Map<String, Object> p = new HashMap<>();// url:圖片地址 image:圖片的base64數(shù)據(jù) 兩個(gè)參數(shù)二選一,詳情見官網(wǎng)APIp.put("url", imageUrl);// front:行駛證主頁 back:行駛證副頁p.put("side", "front");log.info("ocr行駛證識別請求路徑:{},請求參數(shù):{}",url,p);return postJson(url, token, JSON.toJSONString(p));}
}
調(diào)用此接口的流程就是:獲取token后設(shè)置請求頭,發(fā)起請求獲得結(jié)果
三、接口測試
? ? ? ? 3.1、測試接口
@RestController
public class HuaWeiObsController {@Autowiredprivate ObsService ObsService;@Autowiredprivate OcrUtil ocrUtil;@ApiOperation(value = "上傳圖片文件",notes = "xxxxx")@PostMapping("/uploadImgFile")public Result upload(MultipartFile file){String url = ObsService.upload(file);// 行駛證識別/* Result result = ocrUtil.vehicleLicense(ocrUtil.getTokenByAKSK(), url);System.out.println("調(diào)用華為云行駛證識別結(jié)果:"+result.toString());Map<String, Object> data = result.getData();Object data1 = data.get("data");JSONObject jsonObject = JSON.parseObject(data1.toString());String result1 = jsonObject.get("result").toString();System.out.println(result1);vehicleLicense vehicleLicense = JSON.parseObject(result1, vehicleLicense.class);System.out.println("orc識別結(jié)果是:"+vehicleLicense.toString());return Result.ok().data("result",vehicleLicense).data("url",url);*/// 駕駛證識別Result result = ocrUtil.driverLicense(ocrUtil.getTokenByAKSK(), url);System.out.println("調(diào)度接口獲取的結(jié)果集:"+result);Map<String, Object> data = result.getData();Object data1 = data.get("data");JSONObject jsonObject = JSON.parseObject(data1.toString());String result1 = jsonObject.get("result").toString();System.out.println(result1);drivingLicence drivingLicence = JSON.parseObject(result1, drivingLicence.class);System.out.println("orc識別結(jié)果是:"+drivingLicence.toString());return Result.ok().data("result",drivingLicence).data("url",url);}
}
這里的文件上傳用的是華為云的OBS服務(wù),上傳圖片后拿到該圖片對應(yīng)的地址,注意:此圖片地址必須要可以訪問,如設(shè)置訪問權(quán)限則會調(diào)用接口失敗!
? ? ? ? 3.2、結(jié)果
?
?
?四、實(shí)際工作中遇到的問題
? ? ? ? 4.1、前端傳值問題
問題描述:由于前端使用的是根據(jù)el-upload封裝后的組件,我發(fā)現(xiàn)駕駛證和行駛證上傳到的是同一個(gè)接口,那這樣就分不清上傳的駕駛證還是行駛證。
解決辦法:在調(diào)用后端接口傳入圖片類型字段,判斷是駕駛證還是行駛證
:action="this.$http.adornUrl(`/proxyKpiApi/${config.uploadUrl}?${config.id ? `id=${config.id}&` : ''}token=${$cookie.get('token')}&${config.type ? `type=${config.type}` : ''}`)"
?
? ? ? ? 4.2、后端獲取數(shù)據(jù)問題
問題描述:項(xiàng)目中使用的華為云obs文件上傳服務(wù),但是上傳后獲得的圖片地址因?yàn)榘踩钥紤],不能直接訪問,導(dǎo)致調(diào)用接口失敗。
?
// openfeign駕駛證服務(wù)@PostMapping(value = "/performance/driverLicense", params = "{url={url}}")R driverLicense(@RequestParam("url") String url);// openfeign行駛證服務(wù)@PostMapping(value = "/performance/vehicleLicense", params = "{url={url}}")R vehicleLicense(@RequestParam("url") String url);
解決辦法:將上傳的文件轉(zhuǎn)換成base64格式,調(diào)用接口時(shí)改成使用image參數(shù),圖片的base64數(shù)據(jù)。
if(StringUtils.isNotBlank(type)){byte[] fileBytes = file.getBytes();// 將上傳的文件轉(zhuǎn)換成base64格式String base64String = Base64.getEncoder().encodeToString(fileBytes);if(type.equals("driverLicense")){// 遠(yuǎn)程調(diào)用識別駕駛證服務(wù)com.ruoyi.phaseone.common.utils.R r = carrierPerformanceService.driverLicense(base64String);log.info("ocr駕駛證識別請求結(jié)果:{}",r);if(String.valueOf(r.get("code")).equals("0")){Object data = r.get("data");JSONObject jsonObject = JSON.parseObject(data.toString());String result1 = jsonObject.get("result").toString();DrivingLicenceEntity drivingLicenceEntity = JSON.parseObject(result1, DrivingLicenceEntity.class);map.put("ocrResult",drivingLicenceEntity);}}else if(type.equals("vehicleLicense")){// 遠(yuǎn)程調(diào)用識別行駛證服務(wù)com.ruoyi.phaseone.common.utils.R r = carrierPerformanceService.vehicleLicense(base64String);log.info("ocr行駛證識別請求結(jié)果:{}",r);if(String.valueOf(r.get("code")).equals("0")){Object data = r.get("data");JSONObject jsonObject = JSON.parseObject(data.toString());String result1 = jsonObject.get("result").toString();VehicleLicenseEntity vehicleLicenseEntity = JSON.parseObject(result1, VehicleLicenseEntity.class);map.put("ocrResult",vehicleLicenseEntity);}}}
????????4.3、使用openfeign調(diào)用接口報(bào)錯(cuò)
問題描述:按照上面步驟修改后,由于項(xiàng)目是微服務(wù)架構(gòu),文件上傳服務(wù)和前端調(diào)用的接口不在同一個(gè)服務(wù)上,所以要使用openfeign遠(yuǎn)程調(diào)用。但是調(diào)用的過程中報(bào)錯(cuò)了。報(bào)錯(cuò)信息:[<h1>Bad Message 414</h1><pre>reason: URI Too Long</pre>]
解決辦法:此問題是因?yàn)閳D片數(shù)據(jù)轉(zhuǎn)換成base64后,通過遠(yuǎn)程調(diào)用傳的值URI太長了,因此我們將接口改造一下,將參數(shù)改成對象。
@Data
public class ImageEntity implements Serializable {private String imageUrl;private String imageBase64;
}
// openfeign駕駛證服務(wù)@PostMapping( "/performance/driverLicense")R driverLicense(@RequestBody ImageEntity image);// openfeign行駛證服務(wù)@PostMapping("/performance/vehicleLicense")R vehicleLicense(@RequestBody ImageEntity image);
if(StringUtils.isNotBlank(type)){byte[] fileBytes = file.getBytes();// 將上傳的文件轉(zhuǎn)換成base64格式String base64String = Base64.getEncoder().encodeToString(fileBytes);ImageEntity image =new ImageEntity();image.setImageBase64(base64String);if(type.equals("driverLicense")){// 遠(yuǎn)程調(diào)用識別駕駛證服務(wù)com.ruoyi.phaseone.common.utils.R r = carrierPerformanceService.driverLicense(image);log.info("ocr駕駛證識別請求結(jié)果:{}",r);if(String.valueOf(r.get("code")).equals("0")){Object data = r.get("data");JSONObject jsonObject = JSON.parseObject(data.toString());String result1 = jsonObject.get("result").toString();DrivingLicenceEntity drivingLicenceEntity = JSON.parseObject(result1, DrivingLicenceEntity.class);map.put("ocrResult",drivingLicenceEntity);}}else if(type.equals("vehicleLicense")){// 遠(yuǎn)程調(diào)用識別行駛證服務(wù)com.ruoyi.phaseone.common.utils.R r = carrierPerformanceService.vehicleLicense(image);log.info("ocr行駛證識別請求結(jié)果:{}",r);if(String.valueOf(r.get("code")).equals("0")){Object data = r.get("data");JSONObject jsonObject = JSON.parseObject(data.toString());String result1 = jsonObject.get("result").toString();VehicleLicenseEntity vehicleLicenseEntity = JSON.parseObject(result1, VehicleLicenseEntity.class);map.put("ocrResult",vehicleLicenseEntity);}}}
????????4.3、前端顯示問題
問題描述:調(diào)用接口成功后,由于前端使用的是el-upload封裝后的組件,用的watch函數(shù)監(jiān)聽值的變化,每次打開該控件都會顯示其結(jié)果。
watch: {'dataForm.carLicence.attachments' (newVal, oldVal) {}
解決方案:判斷newVal中的ocrResult是否為空,不為空在賦值,因?yàn)榭梢陨蟼鞫鄠€(gè)文件,所以每次更新選取集合中最后一個(gè)元素的數(shù)據(jù)
watch: {'dataForm.carLicence.attachments' (newVal, oldVal) {if (newVal[newVal.length - 1] && newVal[newVal.length - 1].ocrResult !== undefined && newVal[newVal.length - 1].ocrResult !== null) {// 車牌號this.dataForm.carNumber = newVal[newVal.length - 1].ocrResult.number;// 發(fā)動(dòng)機(jī)號this.dataForm.engineNumber = newVal[newVal.length - 1].ocrResult.engine_no;// 所有人this.dataForm.carLicence.person = newVal[newVal.length - 1].ocrResult.name;// 品牌型號this.dataForm.carLicence.brandModel = newVal[newVal.length - 1].ocrResult.model;// 注冊日期this.dataForm.carLicence.registerTime = newVal[newVal.length - 1].ocrResult.register_date;// 發(fā)證日期this.dataForm.carLicence.certificationTime = newVal[newVal.length - 1].ocrResult.issue_date;}}},