123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411 |
- package cn.com.qmth.examcloud.web.facepp;
- import java.util.concurrent.TimeUnit;
- import org.apache.commons.codec.binary.Base64;
- import org.apache.commons.compress.utils.IOUtils;
- import org.apache.commons.lang3.StringUtils;
- import org.apache.http.HttpEntity;
- import org.apache.http.HttpStatus;
- import org.apache.http.client.config.CookieSpecs;
- import org.apache.http.client.config.RequestConfig;
- import org.apache.http.client.methods.CloseableHttpResponse;
- import org.apache.http.client.methods.HttpGet;
- import org.apache.http.client.methods.HttpPost;
- import org.apache.http.entity.mime.MultipartEntityBuilder;
- import org.apache.http.impl.client.CloseableHttpClient;
- import org.apache.http.impl.client.HttpClients;
- import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
- import org.apache.http.util.EntityUtils;
- import com.alibaba.fastjson.JSON;
- import com.alibaba.fastjson.JSONObject;
- import cn.com.qmth.examcloud.commons.exception.ExamCloudRuntimeException;
- import cn.com.qmth.examcloud.commons.exception.StatusException;
- import cn.com.qmth.examcloud.commons.helpers.JsonHttpResponseHolder;
- import cn.com.qmth.examcloud.commons.logging.ExamCloudLog;
- import cn.com.qmth.examcloud.commons.logging.ExamCloudLogFactory;
- import cn.com.qmth.examcloud.web.bootstrap.PropertyHolder;
- /**
- * face++ 客户端
- *
- * @author WANGWEI
- * @date 2019年9月16日
- * @Copyright (c) 2018-? http://qmth.com.cn All Rights Reserved.
- */
- public class FaceppClient {
- protected static ExamCloudLog log = ExamCloudLogFactory.getLog(FaceppClient.class);
- private static CloseableHttpClient httpclient;
- private static RequestConfig requestConfig;
- private static FaceppClient faceppClient;
- private static String apiKey;
- private static String apiSecret;
- private static String compareUrl = "https://api-cn.faceplusplus.com/facepp/v3/compare";
- private FaceppClient() {
- }
- /**
- * 获取单例
- *
- * @author WANGWEI
- * @return
- */
- public static FaceppClient getClient() {
- if (null == faceppClient) {
- synchronized (FaceppClient.class) {
- if (null == faceppClient) {
- faceppClient = new FaceppClient();
- }
- }
- }
- return faceppClient;
- }
- static {
- PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager(60,
- TimeUnit.SECONDS);
- cm.setValidateAfterInactivity(1000);
- cm.setMaxTotal(8000);
- cm.setDefaultMaxPerRoute(200);
- requestConfig = RequestConfig.custom().setConnectionRequestTimeout(500)
- .setSocketTimeout(10000).setConnectTimeout(10000)
- .setCookieSpec(CookieSpecs.IGNORE_COOKIES).build();
- httpclient = HttpClients.custom().setConnectionManager(cm).disableAutomaticRetries()
- .setDefaultRequestConfig(requestConfig).build();
- apiKey = PropertyHolder.getString("$facepp.apiKey");
- apiSecret = PropertyHolder.getString("$facepp.apiSecret");
- if (StringUtils.isBlank(apiKey)) {
- log.error("'facepp.apiKey' is not configured");
- }
- if (StringUtils.isBlank(apiSecret)) {
- log.error("'facepp.apiSecret' is not configured");
- }
- }
- /**
- * 人脸识别
- *
- * @author WANGWEI
- * @param faceToken
- * @param imageUrl
- * @return
- */
- public JsonHttpResponseHolder compareWithTokenAndImageUrl(String faceToken, String imageUrl) {
- if (log.isDebugEnabled()) {
- log.debug("[Face++]. compareWithTokenAndImageUrl(String,String); faceToken=" + faceToken
- + "; imageUrl=" + imageUrl);
- }
- String url = System.getProperty("facepp.compare.url");
- if (StringUtils.isBlank(url)) {
- url = compareUrl;
- }
- HttpPost httpPost = new HttpPost(url);
- httpPost.setConfig(FaceppClient.requestConfig);
- MultipartEntityBuilder builder = MultipartEntityBuilder.create();
- builder.addTextBody("api_key", apiKey);
- builder.addTextBody("api_secret", apiSecret);
- builder.addTextBody("face_token1", faceToken);
- builder.addTextBody("image_url2", imageUrl);
- HttpEntity httpEntity = builder.build();
- httpPost.setEntity(httpEntity);
- CloseableHttpResponse response = null;
- JsonHttpResponseHolder responseHolder = null;
- long s = System.currentTimeMillis();
- try {
- response = httpclient.execute(httpPost);
- int statusCode = response.getStatusLine().getStatusCode();
- String entityStr = EntityUtils.toString(response.getEntity(), "UTF-8");
- JSONObject obj = JSON.parseObject(entityStr);
- responseHolder = new JsonHttpResponseHolder(statusCode, obj);
- if (HttpStatus.SC_OK != responseHolder.getStatusCode()) {
- log.error("[Face++]. compareWithTokenAndImageUrl(String,String); statusCode="
- + statusCode + "; responseEntity=" + entityStr);
- } else {
- if (log.isDebugEnabled()) {
- log.debug("[Face++]. compareWithTokenAndImageUrl(String,String); statusCode="
- + statusCode + "; responseEntity=" + entityStr);
- }
- }
- } catch (Exception e) {
- log.error("[Face++]. compareWithTokenAndImageUrl(String,String); faceToken=" + faceToken
- + "; imageUrl=" + imageUrl + "; cost " + (System.currentTimeMillis() - s)
- + " ms.", e);
- throw new ExamCloudRuntimeException(e);
- } finally {
- IOUtils.closeQuietly(response);
- }
- if (log.isDebugEnabled()) {
- log.debug("[Face++]. compareWithTokenAndImageUrl(String,String); faceToken=" + faceToken
- + "; imageUrl=" + imageUrl + "; cost " + (System.currentTimeMillis() - s)
- + " ms.");
- }
- return responseHolder;
- }
- /**
- * 人脸识别<br>
- * 优先使用主地址调用face++<br>
- * 主地址无效时,使用备用地址调用face++.<br>
- * 备用地址也无效时,使用备用地址下载数据,使用下载数据的base64加密串调用face++<br>
- *
- * @author WANGWEI
- *
- * @param faceToken
- * face++预存照片
- * @param imageUrl
- * 主地址
- * @param backupImageUrl
- * 备用地址
- * @return
- * @throws StatusException
- * code为801,802,803表示图片地址无效
- */
- public JsonHttpResponseHolder compareWithTokenAndImageUrl(String faceToken, String imageUrl,
- String backupImageUrl) throws StatusException {
- JsonHttpResponseHolder responseHolder = null;
- boolean exceptionWhenUsingImageUrl = false;
- boolean exceptionWhenUsingBackupImageUrl = false;
- try {
- responseHolder = compareWithTokenAndImageUrl(faceToken, imageUrl);
- } catch (ExamCloudRuntimeException e) {
- exceptionWhenUsingImageUrl = true;
- }
- if (exceptionWhenUsingImageUrl) {
- try {
- responseHolder = compareWithTokenAndImageUrl(faceToken, backupImageUrl);
- } catch (ExamCloudRuntimeException e) {
- exceptionWhenUsingBackupImageUrl = true;
- }
- } else {
- if (HttpStatus.SC_OK == responseHolder.getStatusCode()) {
- return responseHolder;
- }
- String errMsg = responseHolder.getRespBody().getString("error_message");
- if (retry(errMsg)) {
- try {
- responseHolder = compareWithTokenAndImageUrl(faceToken, backupImageUrl);
- } catch (ExamCloudRuntimeException e) {
- exceptionWhenUsingBackupImageUrl = true;
- }
- }
- }
- if (HttpStatus.SC_OK == responseHolder.getStatusCode()) {
- return responseHolder;
- }
- String errMsg = responseHolder.getRespBody().getString("error_message");
- if (exceptionWhenUsingBackupImageUrl || retry(errMsg)) {
- HttpGet get = new HttpGet(backupImageUrl);
- get.setConfig(FaceppClient.requestConfig);
- CloseableHttpResponse response = null;
- String imageBase64 = null;
- long s = System.currentTimeMillis();
- try {
- response = httpclient.execute(get);
- if (HttpStatus.SC_OK != response.getStatusLine().getStatusCode()) {
- throw new StatusException("801",
- "fail to download file. url=" + backupImageUrl);
- }
- byte[] byteArray = EntityUtils.toByteArray(response.getEntity());
- if (100 > byteArray.length) {
- throw new StatusException("802", "invalid image size. url=" + backupImageUrl);
- }
- imageBase64 = Base64.encodeBase64String(byteArray);
- } catch (StatusException e) {
- log.error("fail to download file. url=" + backupImageUrl, e);
- throw e;
- } catch (Exception e) {
- log.error("fail to download file. url=" + backupImageUrl, e);
- throw new StatusException("803", "fail to download file. url=" + backupImageUrl, e);
- } finally {
- IOUtils.closeQuietly(response);
- }
- if (log.isDebugEnabled()) {
- log.debug(
- "[Face++]. compareWithTokenAndImageUrl(String,String,String); download image; url="
- + backupImageUrl + "; cost " + (System.currentTimeMillis() - s)
- + " ms.");
- }
- responseHolder = compareWithTokenAndBase64(faceToken, imageBase64);
- }
- return responseHolder;
- }
- private boolean retry(String errMsg) {
- if (null != errMsg) {
- if (errMsg.startsWith("INVALID_IMAGE_URL")
- || errMsg.startsWith("IMAGE_DOWNLOAD_TIMEOUT")) {
- return true;
- }
- }
- return false;
- }
- /**
- * 人脸识别
- *
- * @author WANGWEI
- * @param faceToken
- * @param imageBase64
- * @return
- */
- public JsonHttpResponseHolder compareWithTokenAndBase64(String faceToken, String imageBase64) {
- String url = System.getProperty("facepp.compare.url");
- if (StringUtils.isBlank(url)) {
- url = compareUrl;
- }
- HttpPost httpPost = new HttpPost(url);
- httpPost.setConfig(FaceppClient.requestConfig);
- MultipartEntityBuilder builder = MultipartEntityBuilder.create();
- builder.addTextBody("api_key", apiKey);
- builder.addTextBody("api_secret", apiSecret);
- builder.addTextBody("face_token1", faceToken);
- builder.addTextBody("image_base64_2", imageBase64);
- HttpEntity httpEntity = builder.build();
- httpPost.setEntity(httpEntity);
- CloseableHttpResponse response = null;
- JsonHttpResponseHolder responseHolder = null;
- long s = System.currentTimeMillis();
- try {
- response = httpclient.execute(httpPost);
- int statusCode = response.getStatusLine().getStatusCode();
- String entityStr = EntityUtils.toString(response.getEntity(), "UTF-8");
- JSONObject obj = JSON.parseObject(entityStr);
- responseHolder = new JsonHttpResponseHolder(statusCode, obj);
- if (HttpStatus.SC_OK != responseHolder.getStatusCode()) {
- log.error("[Face++]. compareWithTokenAndBase64(String,String); statusCode="
- + statusCode + "; responseEntity=" + entityStr);
- } else {
- if (log.isDebugEnabled()) {
- log.debug("[Face++]. compareWithTokenAndBase64(String,String); statusCode="
- + statusCode + "; responseEntity=" + entityStr);
- }
- }
- } catch (Exception e) {
- throw new ExamCloudRuntimeException(e);
- } finally {
- IOUtils.closeQuietly(response);
- }
- if (log.isDebugEnabled()) {
- log.debug("[Face++]. compareWithTokenAndBase64(String,String); faceToken=" + faceToken
- + "; imageBase64=" + imageBase64 + "; cost " + (System.currentTimeMillis() - s)
- + " ms.");
- }
- return responseHolder;
- }
- /**
- * 人脸识别
- *
- * @author WANGWEI
- * @param imageUrl1
- * @param imageUrl2
- * @return
- */
- public JsonHttpResponseHolder compareWithImageUrl(String imageUrl1, String imageUrl2) {
- String url = System.getProperty("facepp.compare.url");
- if (StringUtils.isBlank(url)) {
- url = compareUrl;
- }
- HttpPost httpPost = new HttpPost(url);
- httpPost.setConfig(FaceppClient.requestConfig);
- MultipartEntityBuilder builder = MultipartEntityBuilder.create();
- builder.addTextBody("api_key", apiKey);
- builder.addTextBody("api_secret", apiSecret);
- builder.addTextBody("image_url1", imageUrl1);
- builder.addTextBody("image_url2", imageUrl2);
- HttpEntity httpEntity = builder.build();
- httpPost.setEntity(httpEntity);
- CloseableHttpResponse response = null;
- JsonHttpResponseHolder responseHolder = null;
- long s = System.currentTimeMillis();
- try {
- response = httpclient.execute(httpPost);
- int statusCode = response.getStatusLine().getStatusCode();
- String entityStr = EntityUtils.toString(response.getEntity(), "UTF-8");
- JSONObject obj = JSON.parseObject(entityStr);
- responseHolder = new JsonHttpResponseHolder(statusCode, obj);
- if (HttpStatus.SC_OK != responseHolder.getStatusCode()) {
- log.error("[Face++]. compareWithImageUrl(String,String); statusCode=" + statusCode
- + "; responseEntity=" + entityStr);
- } else {
- if (log.isDebugEnabled()) {
- log.debug("[Face++]. compareWithImageUrl(String,String); statusCode="
- + statusCode + "; responseEntity=" + entityStr);
- }
- }
- } catch (Exception e) {
- throw new ExamCloudRuntimeException(e);
- } finally {
- IOUtils.closeQuietly(response);
- }
- if (log.isDebugEnabled()) {
- log.debug("[Face++]. compareWithImageUrl(String,String); image_url1=" + imageUrl1
- + "; imageUrl2=" + imageUrl2 + "; cost " + (System.currentTimeMillis() - s)
- + " ms.");
- }
- return responseHolder;
- }
- }
|