diff --git a/src/main/java/com/ycwl/basic/facebody/adapter/BceFaceBodyAdapter.java b/src/main/java/com/ycwl/basic/facebody/adapter/BceFaceBodyAdapter.java index fdf5ead2..8901ca78 100644 --- a/src/main/java/com/ycwl/basic/facebody/adapter/BceFaceBodyAdapter.java +++ b/src/main/java/com/ycwl/basic/facebody/adapter/BceFaceBodyAdapter.java @@ -1,5 +1,6 @@ package com.ycwl.basic.facebody.adapter; +import cn.hutool.core.codec.Base64; import com.baidu.aip.face.AipFace; import com.ycwl.basic.facebody.entity.AddFaceResp; import com.ycwl.basic.facebody.entity.BceFaceBodyConfig; @@ -15,8 +16,13 @@ import lombok.extern.slf4j.Slf4j; import org.json.JSONArray; import org.json.JSONObject; +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.ByteArrayOutputStream; +import java.io.IOException; import java.math.BigDecimal; import java.math.RoundingMode; +import java.net.URL; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -152,10 +158,34 @@ public class BceFaceBodyAdapter implements IFaceBodyAdapter { } catch (InterruptedException ignored) { } JSONObject response = client.addUser(faceUrl, "URL", dbName, entityId, options); - if (response.getInt("error_code") == 0) { + int errorCode = response.getInt("error_code"); + if (errorCode == 0) { AddFaceResp resp = new AddFaceResp(); resp.setScore(100f); return resp; + } else if (errorCode == 222204) { + // error_code: 222204 表示无法正常访问URL图片,尝试下载并转换为base64后重试 + log.warn("无法正常访问URL图片,错误码: 222204,尝试下载图片转base64后重试,URL: {}", faceUrl); + String base64Image = downloadImageAsBase64(faceUrl); + if (base64Image != null) { + try { + addEntityLimiter.acquire(); + } catch (InterruptedException ignored) { + } + JSONObject retryResponse = client.addUser(base64Image, "BASE64", dbName, entityId, options); + if (retryResponse.getInt("error_code") == 0) { + log.info("使用base64重试添加人脸成功,entityId: {}", entityId); + AddFaceResp resp = new AddFaceResp(); + resp.setScore(100f); + return resp; + } else { + log.warn("使用base64重试添加人脸仍失败!{}", retryResponse); + return null; + } + } else { + log.error("下载图片转base64失败,无法重试,URL: {}", faceUrl); + return null; + } } else { log.warn("创建人脸失败!{}", response); return null; @@ -395,7 +425,53 @@ public class BceFaceBodyAdapter implements IFaceBodyAdapter { return client; } } - + + /** + * 下载图片并转换为base64字符串 + * + * @param imageUrl 图片URL + * @return base64编码的图片字符串,失败返回null + */ + private String downloadImageAsBase64(String imageUrl) { + BufferedImage image = null; + ByteArrayOutputStream baos = null; + try { + // 下载图片 + URL url = new URL(imageUrl.replace("oss-cn-shanghai.aliyuncs.com", "oss-cn-shanghai-internal.aliyuncs.com")); + image = ImageIO.read(url); + if (image == null) { + log.error("无法读取图片,URL: {}", imageUrl); + return null; + } + + // 转换为字节数组 + baos = new ByteArrayOutputStream(); + String format = "jpg"; + if (imageUrl.toLowerCase().endsWith(".png")) { + format = "png"; + } + ImageIO.write(image, format, baos); + byte[] imageBytes = baos.toByteArray(); + + // 编码为base64 + return Base64.encode(imageBytes); + } catch (IOException e) { + log.error("下载图片或转换base64失败,URL: {}", imageUrl, e); + return null; + } finally { + if (image != null) { + image.flush(); + } + if (baos != null) { + try { + baos.close(); + } catch (IOException e) { + log.warn("关闭ByteArrayOutputStream失败", e); + } + } + } + } + private IRateLimiter getLimiter(LOCK_TYPE type) { return switch (type) { case ADD_DB ->