cos 上传针对图片保真压缩。
This commit is contained in:
parent
c0b3b74533
commit
bd8e11a663
@ -30,6 +30,7 @@ import com.suisung.mall.common.pojo.dto.OssCallbackResultDTO;
|
|||||||
import com.suisung.mall.common.pojo.dto.OssPolicyResultDTO;
|
import com.suisung.mall.common.pojo.dto.OssPolicyResultDTO;
|
||||||
import com.suisung.mall.common.utils.I18nUtil;
|
import com.suisung.mall.common.utils.I18nUtil;
|
||||||
import com.suisung.mall.common.utils.LogUtil;
|
import com.suisung.mall.common.utils.LogUtil;
|
||||||
|
import com.suisung.mall.common.utils.UploadUtil;
|
||||||
import com.suisung.mall.common.utils.VideoUtil;
|
import com.suisung.mall.common.utils.VideoUtil;
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@ -169,6 +170,9 @@ public class OssServiceImpl implements OssService {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public Map upload(MultipartFile file, UserDto user, String dir, String uploadPath, String uploadName, String fileName) {
|
public Map upload(MultipartFile file, UserDto user, String dir, String uploadPath, String uploadName, String fileName) {
|
||||||
|
// 如果是图片,先压缩图片,再上传到 cos 对象存储
|
||||||
|
file = UploadUtil.compressImageIfNeeded(file, 2048);
|
||||||
|
|
||||||
// 创建临时文件
|
// 创建临时文件
|
||||||
creTempFile(file, dir, uploadName);
|
creTempFile(file, dir, uploadName);
|
||||||
String url = null;
|
String url = null;
|
||||||
|
|||||||
@ -6,8 +6,11 @@ import org.apache.tika.Tika;
|
|||||||
import org.springframework.util.Base64Utils;
|
import org.springframework.util.Base64Utils;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.net.*;
|
import java.net.*;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
@ -437,4 +440,250 @@ public class UploadUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 压缩图片文件以提高质量。
|
||||||
|
* 如果文件大小超过500KB,则在保持宽高比的同时调整大小
|
||||||
|
* 以提高清晰度并减小文件大小。
|
||||||
|
*
|
||||||
|
* @param file 原始图片文件
|
||||||
|
* @param pixelLimit 像素限制
|
||||||
|
* @return 压缩后的图片文件,如果不需要压缩则返回原始文件
|
||||||
|
*/
|
||||||
|
public static MultipartFile compressImageIfNeeded(MultipartFile file, Integer pixelLimit) {
|
||||||
|
if (file == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 检查文件是否为图片格式
|
||||||
|
String contentType = file.getContentType();
|
||||||
|
if (contentType == null || !contentType.startsWith("image/")) {
|
||||||
|
log.debug("文件不是图片格式,跳过压缩: {}", contentType);
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pixelLimit == null) {
|
||||||
|
pixelLimit = 2048;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 小文件直接返回
|
||||||
|
if (file.getSize() <= 512000) { // 500KB
|
||||||
|
log.debug("文件大小在限制范围内 ({} 字节),无需压缩", file.getSize());
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 将MultipartFile转换为BufferedImage
|
||||||
|
BufferedImage originalImage = ImageIO.read(file.getInputStream());
|
||||||
|
if (originalImage == null) {
|
||||||
|
log.warn("读取图片文件失败,跳过压缩");
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
int originalWidth = originalImage.getWidth();
|
||||||
|
int originalHeight = originalImage.getHeight();
|
||||||
|
|
||||||
|
// 小图片直接返回
|
||||||
|
if (originalWidth <= pixelLimit && originalHeight <= pixelLimit) {
|
||||||
|
log.debug("图片尺寸在限制范围内 ({}x{}),无需调整大小", originalWidth, originalHeight);
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算保持宽高比的新尺寸
|
||||||
|
double aspectRatio = (double) originalWidth / originalHeight;
|
||||||
|
int newWidth, newHeight;
|
||||||
|
|
||||||
|
// 目标尺寸:最长边最大为pixelLimit像素
|
||||||
|
if (originalWidth > originalHeight) {
|
||||||
|
newWidth = Math.min(pixelLimit, originalWidth);
|
||||||
|
newHeight = (int) (newWidth / aspectRatio);
|
||||||
|
} else {
|
||||||
|
newHeight = Math.min(pixelLimit, originalHeight);
|
||||||
|
newWidth = (int) (newHeight * aspectRatio);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确保最小尺寸
|
||||||
|
newWidth = Math.max(newWidth, 1);
|
||||||
|
newHeight = Math.max(newHeight, 1);
|
||||||
|
|
||||||
|
log.debug("调整图片尺寸从 {}x{} 到 {}x{}", originalWidth, originalHeight, newWidth, newHeight);
|
||||||
|
|
||||||
|
// 获取图片格式并执行高质量渐进式缩放
|
||||||
|
String format = getImageFormat(file.getOriginalFilename());
|
||||||
|
BufferedImage resizedImage = progressiveResize(originalImage, newWidth, newHeight, format);
|
||||||
|
|
||||||
|
// 转换回MultipartFile
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||||
|
ImageIO.write(resizedImage, format, baos);
|
||||||
|
byte[] compressedBytes = baos.toByteArray();
|
||||||
|
|
||||||
|
log.info("图片从 {} 字节压缩到 {} 字节", file.getSize(), compressedBytes.length);
|
||||||
|
|
||||||
|
return new InMemoryMultipartFile(
|
||||||
|
file.getName(),
|
||||||
|
file.getOriginalFilename(),
|
||||||
|
file.getContentType(),
|
||||||
|
compressedBytes
|
||||||
|
);
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("压缩图片时出错,使用原始文件: {}", e.getMessage(), e);
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 渐进式调整图片大小以提高质量
|
||||||
|
*
|
||||||
|
* @param originalImage 原始图片
|
||||||
|
* @param targetWidth 目标宽度
|
||||||
|
* @param targetHeight 目标高度
|
||||||
|
* @param format 图片格式
|
||||||
|
* @return 调整大小后的图片,质量更好
|
||||||
|
*/
|
||||||
|
private static BufferedImage progressiveResize(BufferedImage originalImage, int targetWidth, int targetHeight, String format) {
|
||||||
|
int currentWidth = originalImage.getWidth();
|
||||||
|
int currentHeight = originalImage.getHeight();
|
||||||
|
|
||||||
|
// 多步缩小以提高质量
|
||||||
|
BufferedImage resizedImage = originalImage;
|
||||||
|
|
||||||
|
while (currentWidth > targetWidth * 2 || currentHeight > targetHeight * 2) {
|
||||||
|
currentWidth = Math.max(targetWidth, currentWidth / 2);
|
||||||
|
currentHeight = Math.max(targetHeight, currentHeight / 2);
|
||||||
|
|
||||||
|
resizedImage = scaleImage(resizedImage, currentWidth, currentHeight, format);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 最终调整到目标尺寸
|
||||||
|
return scaleImage(resizedImage, targetWidth, targetHeight, format);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 使用高质量渲染提示缩放图片
|
||||||
|
*
|
||||||
|
* @param originalImage 原始图片
|
||||||
|
* @param targetWidth 目标宽度
|
||||||
|
* @param targetHeight 目标高度
|
||||||
|
* @param format 图片格式
|
||||||
|
* @return 缩放后的图片
|
||||||
|
*/
|
||||||
|
private static BufferedImage scaleImage(BufferedImage originalImage, int targetWidth, int targetHeight, String format) {
|
||||||
|
int imageType = getImageTypeForFormat(format);
|
||||||
|
BufferedImage scaledImage = new BufferedImage(targetWidth, targetHeight, imageType);
|
||||||
|
Graphics2D g2d = scaledImage.createGraphics();
|
||||||
|
|
||||||
|
// 高质量渲染设置
|
||||||
|
g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
|
||||||
|
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
|
||||||
|
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
|
||||||
|
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
|
||||||
|
g2d.setRenderingHint(RenderingHints.KEY_DITHERING, RenderingHints.VALUE_DITHER_ENABLE);
|
||||||
|
g2d.setRenderingHint(RenderingHints.KEY_ALPHA_INTERPOLATION, RenderingHints.VALUE_ALPHA_INTERPOLATION_QUALITY);
|
||||||
|
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS, RenderingHints.VALUE_FRACTIONALMETRICS_ON);
|
||||||
|
|
||||||
|
g2d.drawImage(originalImage, 0, 0, targetWidth, targetHeight, null);
|
||||||
|
g2d.dispose();
|
||||||
|
|
||||||
|
return scaledImage;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据文件扩展名获取图片格式,支持更多格式
|
||||||
|
*
|
||||||
|
* @param filename 原始文件名
|
||||||
|
* @return 图片格式 (jpg, png, gif 等)
|
||||||
|
*/
|
||||||
|
private static String getImageFormat(String filename) {
|
||||||
|
if (StrUtil.isBlank(filename)) {
|
||||||
|
return "jpg";
|
||||||
|
}
|
||||||
|
|
||||||
|
String extension = filename.substring(filename.lastIndexOf('.') + 1).toLowerCase();
|
||||||
|
switch (extension) {
|
||||||
|
case "png":
|
||||||
|
return "png";
|
||||||
|
case "gif":
|
||||||
|
return "gif";
|
||||||
|
case "bmp":
|
||||||
|
return "bmp";
|
||||||
|
case "wbmp":
|
||||||
|
return "wbmp";
|
||||||
|
case "jpeg":
|
||||||
|
case "jpg":
|
||||||
|
return "jpeg";
|
||||||
|
default:
|
||||||
|
return "jpeg";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据格式确定适当的图片类型以保留透明度
|
||||||
|
*
|
||||||
|
* @param format 图片格式
|
||||||
|
* @return BufferedImage类型
|
||||||
|
*/
|
||||||
|
private static int getImageTypeForFormat(String format) {
|
||||||
|
if ("png".equalsIgnoreCase(format) || "gif".equalsIgnoreCase(format)) {
|
||||||
|
return BufferedImage.TYPE_INT_ARGB; // 保留透明度
|
||||||
|
}
|
||||||
|
return BufferedImage.TYPE_INT_RGB; // JPEG等格式的默认值
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple MultipartFile implementation for in-memory data
|
||||||
|
*/
|
||||||
|
private static class InMemoryMultipartFile implements MultipartFile {
|
||||||
|
private final String name;
|
||||||
|
private final String originalFilename;
|
||||||
|
private final String contentType;
|
||||||
|
private final byte[] content;
|
||||||
|
|
||||||
|
public InMemoryMultipartFile(String name, String originalFilename, String contentType, byte[] content) {
|
||||||
|
this.name = name;
|
||||||
|
this.originalFilename = originalFilename;
|
||||||
|
this.contentType = contentType;
|
||||||
|
this.content = content;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getOriginalFilename() {
|
||||||
|
return originalFilename;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getContentType() {
|
||||||
|
return contentType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return content == null || content.length == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getSize() {
|
||||||
|
return content.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] getBytes() throws IOException {
|
||||||
|
return content;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public InputStream getInputStream() throws IOException {
|
||||||
|
return new ByteArrayInputStream(content);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void transferTo(File dest) throws IOException, IllegalStateException {
|
||||||
|
new FileOutputStream(dest).write(content);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -136,85 +136,124 @@ public class LklTkServiceImpl {
|
|||||||
* 身份证反面:ID_CARD_BEHIND;
|
* 身份证反面:ID_CARD_BEHIND;
|
||||||
* 营业执照:BUSINESS_LICENCE;
|
* 营业执照:BUSINESS_LICENCE;
|
||||||
* 银行卡:BANK_CARD
|
* 银行卡:BANK_CARD
|
||||||
* @return
|
* @return 上传结果及OCR识别信息
|
||||||
*/
|
*/
|
||||||
public CommonResult uploadOcrImg(MultipartFile file, String imgType) {
|
public CommonResult uploadOcrImg(MultipartFile file, String imgType) {
|
||||||
|
// 参数校验
|
||||||
|
if (file == null || StrUtil.isBlank(imgType)) {
|
||||||
|
logger.warn("上传文件参数缺失: imgType={}", imgType);
|
||||||
|
return CommonResult.failed("上传文件或图片类型不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
UserDto currentUser = getCurrentUser();
|
UserDto currentUser = getCurrentUser();
|
||||||
if (currentUser == null) {
|
if (currentUser == null) {
|
||||||
currentUser = new UserDto();
|
currentUser = new UserDto();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file == null || StrUtil.isBlank(imgType)) {
|
// Compress image if needed before processing
|
||||||
return CommonResult.failed("上传文件或图片类型不能为空");
|
MultipartFile processedFile = UploadUtil.compressImageIfNeeded(file, 2048);
|
||||||
|
if (processedFile == null) {
|
||||||
|
logger.warn("上传文件压缩失败: filename={}, imgType={}",
|
||||||
|
file.getOriginalFilename(), imgType);
|
||||||
|
return CommonResult.failed("服务繁忙,请重试!");
|
||||||
}
|
}
|
||||||
|
|
||||||
CommonResult ossImgInfo = ossService.uploadFile(file, currentUser);
|
// 上传文件到OSS
|
||||||
|
CommonResult ossImgInfo = ossService.uploadFile(processedFile, currentUser);
|
||||||
if (ossImgInfo == null) {
|
if (ossImgInfo == null) {
|
||||||
|
logger.error("上传文件到OSS失败,filename={}, imgType={}",
|
||||||
|
processedFile.getOriginalFilename(), imgType);
|
||||||
return CommonResult.failed("上传文件失败");
|
return CommonResult.failed("上传文件失败");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ossImgInfo.getStatus() != ResultCode.SUCCESS.getStatus() || ossImgInfo.getData() == null) {
|
if (ossImgInfo.getStatus() != ResultCode.SUCCESS.getStatus() || ossImgInfo.getData() == null) {
|
||||||
|
logger.error("OSS上传响应异常,filename={}, imgType={}, status={}",
|
||||||
|
processedFile.getOriginalFilename(), imgType, ossImgInfo.getStatus());
|
||||||
return CommonResult.failed(ossImgInfo.getMsg());
|
return CommonResult.failed(ossImgInfo.getMsg());
|
||||||
}
|
}
|
||||||
|
|
||||||
String imgURL = JSONUtil.parseObj(ossImgInfo.getData()).getStr("url");
|
String imgURL = JSONUtil.parseObj(ossImgInfo.getData()).getStr("url");
|
||||||
|
logger.debug("文件上传OSS成功,filename={}", processedFile.getOriginalFilename());
|
||||||
|
|
||||||
|
// 获取拉卡拉认证信息
|
||||||
String authorization = getLklTkAuthorization();
|
String authorization = getLklTkAuthorization();
|
||||||
if (StrUtil.isBlank(authorization)) {
|
if (StrUtil.isBlank(authorization)) {
|
||||||
|
logger.error("获取拉卡拉token失败,filename={}, imgType={}",
|
||||||
|
processedFile.getOriginalFilename(), imgType);
|
||||||
return CommonResult.failed("获取拉卡拉token失败");
|
return CommonResult.failed("获取拉卡拉token失败");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 构造请求头
|
||||||
JSONObject header = new JSONObject();
|
JSONObject header = new JSONObject();
|
||||||
header.put("Authorization", authorization);
|
header.put("Authorization", authorization);
|
||||||
|
|
||||||
|
// 文件转Base64
|
||||||
String fileBase64 = UploadUtil.multipartFileToBase64(file);
|
String fileBase64 = UploadUtil.multipartFileToBase64(processedFile);
|
||||||
if (StrUtil.isBlank(fileBase64)) {
|
if (StrUtil.isBlank(fileBase64)) {
|
||||||
|
logger.error("文件转换Base64失败,filename={}, imgType={}",
|
||||||
|
processedFile.getOriginalFilename(), imgType);
|
||||||
return CommonResult.failed("解析文件转换失败");
|
return CommonResult.failed("解析文件转换失败");
|
||||||
}
|
}
|
||||||
// Base64Utils.encodeToString(file.getBytes());
|
|
||||||
|
|
||||||
|
// 构造请求体
|
||||||
JSONObject requestBody = new JSONObject();
|
JSONObject requestBody = new JSONObject();
|
||||||
requestBody.put("fileBase64", fileBase64);
|
requestBody.put("fileBase64", fileBase64);
|
||||||
requestBody.put("imgType", imgType);
|
requestBody.put("imgType", imgType);
|
||||||
requestBody.put("sourcechnl", "0"); // 来源: 0:PC,1:安卓,2:IOS
|
requestBody.put("sourcechnl", "0"); // 来源: 0:PC,1:安卓,2:IOS
|
||||||
requestBody.put("isOcr", "true");
|
requestBody.put("isOcr", "true");
|
||||||
|
|
||||||
|
// 构造请求路径
|
||||||
String urlPath = "/sit/htkregistration/file/base/upload";
|
String urlPath = "/sit/htkregistration/file/base/upload";
|
||||||
if (isLklProd) {
|
if (isLklProd) {
|
||||||
// 生产环境启用
|
|
||||||
urlPath = "/registration/file/base/upload";
|
urlPath = "/registration/file/base/upload";
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
// 发送请求并获取响应
|
||||||
ResponseEntity<JSONObject> updResponse = RestTemplateHttpUtil.sendPostBodyBackEntity(buildLklTkUrl(urlPath), header, requestBody, JSONObject.class);
|
ResponseEntity<JSONObject> updResponse = RestTemplateHttpUtil.sendPostBodyBackEntity(
|
||||||
if (ObjectUtil.isEmpty(updResponse)
|
buildLklTkUrl(urlPath), header, requestBody, JSONObject.class);
|
||||||
|| updResponse.getStatusCode() != HttpStatus.OK
|
|
||||||
|| ObjectUtil.isEmpty(updResponse.getBody())) {
|
logger.info("调用拉卡拉文件上传接口,filename={}, imgType={}",
|
||||||
|
processedFile.getOriginalFilename(), imgType);
|
||||||
|
|
||||||
|
// 检查响应有效性
|
||||||
|
if (ObjectUtil.isEmpty(updResponse) ||
|
||||||
|
updResponse.getStatusCode() != HttpStatus.OK ||
|
||||||
|
ObjectUtil.isEmpty(updResponse.getBody())) {
|
||||||
|
logger.error("拉卡拉文件上传响应数据异常,filename={}, imgType={}",
|
||||||
|
processedFile.getOriginalFilename(), imgType);
|
||||||
return CommonResult.failed("上传文件返回值有误");
|
return CommonResult.failed("上传文件返回值有误");
|
||||||
}
|
}
|
||||||
|
|
||||||
// {batchNo,status,url,showUrl,result{} }
|
// 提取上传结果
|
||||||
JSONObject updObj = updResponse.getBody();
|
JSONObject updObj = updResponse.getBody();
|
||||||
String batchNo = updObj.getStr("batchNo");
|
String batchNo = updObj.getStr("batchNo");
|
||||||
if (StrUtil.isBlank(batchNo)) {
|
if (StrUtil.isBlank(batchNo)) {
|
||||||
|
logger.error("拉卡拉文件上传返回批次号为空,filename={}, imgType={}",
|
||||||
|
processedFile.getOriginalFilename(), imgType);
|
||||||
return CommonResult.failed("上传文件返回值有误");
|
return CommonResult.failed("上传文件返回值有误");
|
||||||
}
|
}
|
||||||
|
|
||||||
updObj.put("cosURL", imgURL);
|
updObj.put("cosURL", imgURL);
|
||||||
|
logger.info("拉卡拉文件上传成功,filename={}, imgType={}, batchNo={}",
|
||||||
|
processedFile.getOriginalFilename(), imgType, batchNo);
|
||||||
|
|
||||||
return CommonResult.success(updObj);
|
return CommonResult.success(updObj);
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.error("上传文件失败: ", e.getMessage());
|
logger.error("上传文件过程发生异常,filename={}, imgType={}",
|
||||||
|
file != null ? file.getOriginalFilename() : "unknown", imgType, e);
|
||||||
return CommonResult.failed("上传文件失败:" + e.getMessage());
|
return CommonResult.failed("上传文件失败:" + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据上传的图片的批次号,获取 OCR 识别结果
|
* 根据上传的图片的批次号,获取 OCR 识别结果
|
||||||
*
|
*
|
||||||
* @param batchNo
|
* @param batchNo 批次号
|
||||||
* @param imgType * ID_CARD_FRONT 身份证正⾯
|
* @param imgType 图片类型
|
||||||
|
* * ID_CARD_FRONT 身份证正⾯
|
||||||
* * ID_CARD_BEHIND 身份证反⾯
|
* * ID_CARD_BEHIND 身份证反⾯
|
||||||
* * BUSINESS_LICENCE 营业执照照⽚
|
* * BUSINESS_LICENCE 营业执照照⽚
|
||||||
* * BANK_CARD 银行卡(企业对公不需要传)
|
* * BANK_CARD 银行卡(企业对公不需要传)
|
||||||
@ -227,55 +266,70 @@ public class LklTkServiceImpl {
|
|||||||
* * SETTLE_ID_CARD_FRONT 结算人身份证人像面
|
* * SETTLE_ID_CARD_FRONT 结算人身份证人像面
|
||||||
* * SETTLE_ID_CARD_BEHIND 结算人身份证国徽面
|
* * SETTLE_ID_CARD_BEHIND 结算人身份证国徽面
|
||||||
* * LETTER_OF_AUTHORIZATION 法人授权涵
|
* * LETTER_OF_AUTHORIZATION 法人授权涵
|
||||||
* @return
|
* @return OCR识别结果
|
||||||
*/
|
*/
|
||||||
public CommonResult imgOcrResult(String batchNo, String imgType) {
|
public CommonResult imgOcrResult(String batchNo, String imgType) {
|
||||||
|
// 参数校验
|
||||||
if (StrUtil.isBlank(batchNo) || StrUtil.isBlank(imgType)) {
|
if (StrUtil.isBlank(batchNo) || StrUtil.isBlank(imgType)) {
|
||||||
|
logger.warn("OCR识别参数缺失: batchNo={}, imgType={}", batchNo, imgType);
|
||||||
return CommonResult.failed("批次号或图片类型不能为空");
|
return CommonResult.failed("批次号或图片类型不能为空");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 调用 OCR 识别接口
|
try {
|
||||||
|
// 获取认证信息
|
||||||
String authorization = getLklTkAuthorization();
|
String authorization = getLklTkAuthorization();
|
||||||
if (StrUtil.isBlank(authorization)) {
|
if (StrUtil.isBlank(authorization)) {
|
||||||
|
logger.error("获取拉卡拉token失败,batchNo={}, imgType={}", batchNo, imgType);
|
||||||
return CommonResult.failed("获取拉卡拉token失败");
|
return CommonResult.failed("获取拉卡拉token失败");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 构造请求头
|
||||||
JSONObject header = new JSONObject();
|
JSONObject header = new JSONObject();
|
||||||
header.put("Authorization", authorization);
|
header.put("Authorization", authorization);
|
||||||
|
|
||||||
|
// 构造请求体
|
||||||
JSONObject ocrRequestBody = new JSONObject();
|
JSONObject ocrRequestBody = new JSONObject();
|
||||||
ocrRequestBody.put("batchNo", batchNo);
|
ocrRequestBody.put("batchNo", batchNo);
|
||||||
ocrRequestBody.put("imgType", imgType);
|
ocrRequestBody.put("imgType", imgType);
|
||||||
logger.info("ocr请求参数:{}", ocrRequestBody);
|
logger.info("调用OCR识别接口,batchNo={}, imgType={}", batchNo, imgType);
|
||||||
|
|
||||||
|
// 构造请求路径
|
||||||
String urlPath = "/sit/htkregistration/ocr/result";
|
String urlPath = "/sit/htkregistration/ocr/result";
|
||||||
if (isLklProd) {
|
if (isLklProd) {
|
||||||
// 生产环境启用
|
|
||||||
urlPath = "/registration/ocr/result";
|
urlPath = "/registration/ocr/result";
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
// 发送请求并获取响应
|
||||||
ResponseEntity<JSONObject> ocrResponse = RestTemplateHttpUtil.sendPostBodyBackEntity(buildLklTkUrl(urlPath), header, ocrRequestBody, JSONObject.class);
|
ResponseEntity<JSONObject> ocrResponse = RestTemplateHttpUtil.sendPostBodyBackEntity(
|
||||||
if (ObjectUtil.isEmpty(ocrResponse)
|
buildLklTkUrl(urlPath), header, ocrRequestBody, JSONObject.class);
|
||||||
|| ocrResponse.getStatusCode() != HttpStatus.OK
|
|
||||||
|| ObjectUtil.isEmpty(ocrResponse.getBody())) {
|
// 检查响应有效性
|
||||||
|
if (ObjectUtil.isEmpty(ocrResponse) ||
|
||||||
|
ocrResponse.getStatusCode() != HttpStatus.OK ||
|
||||||
|
ObjectUtil.isEmpty(ocrResponse.getBody())) {
|
||||||
|
logger.error("OCR识别响应数据异常,batchNo={}, imgType={}", batchNo, imgType);
|
||||||
return CommonResult.failed("OCR响应数据有误");
|
return CommonResult.failed("OCR响应数据有误");
|
||||||
}
|
}
|
||||||
|
|
||||||
JSONObject ocrObj = ocrResponse.getBody().get("result", JSONObject.class);
|
// 提取OCR结果
|
||||||
logger.info("ocr返回结果:{}", ocrResponse);
|
JSONObject result = ocrResponse.getBody();
|
||||||
|
JSONObject ocrObj = result.get("result", JSONObject.class);
|
||||||
|
logger.info("OCR识别成功,batchNo={}, imgType={}", batchNo, imgType);
|
||||||
|
|
||||||
if (ObjectUtil.isEmpty(ocrObj)) {
|
if (ObjectUtil.isEmpty(ocrObj)) {
|
||||||
|
logger.warn("OCR识别返回结果为空,batchNo={}, imgType={}", batchNo, imgType);
|
||||||
return CommonResult.failed("OCR返回结果有误");
|
return CommonResult.failed("OCR返回结果有误");
|
||||||
}
|
}
|
||||||
|
|
||||||
return CommonResult.success(ocrObj);
|
return CommonResult.success(ocrObj);
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.error("OCR识别失败: ", e.getMessage());
|
logger.error("OCR识别过程发生异常,batchNo={}, imgType={}", batchNo, imgType, e);
|
||||||
return CommonResult.failed("OCR识别失败:" + e.getMessage());
|
return CommonResult.failed("OCR识别失败:" + e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* (商户进件前)请求获取token
|
* (商户进件前)请求获取token
|
||||||
*
|
*
|
||||||
|
|||||||
@ -27,6 +27,7 @@ import com.suisung.mall.common.pojo.dto.OssPolicyResultDTO;
|
|||||||
import com.suisung.mall.common.utils.CheckUtil;
|
import com.suisung.mall.common.utils.CheckUtil;
|
||||||
import com.suisung.mall.common.utils.I18nUtil;
|
import com.suisung.mall.common.utils.I18nUtil;
|
||||||
import com.suisung.mall.common.utils.LogUtil;
|
import com.suisung.mall.common.utils.LogUtil;
|
||||||
|
import com.suisung.mall.common.utils.UploadUtil;
|
||||||
import com.suisung.mall.shop.base.service.AccountBaseConfigService;
|
import com.suisung.mall.shop.base.service.AccountBaseConfigService;
|
||||||
import com.suisung.mall.shop.page.service.OssService;
|
import com.suisung.mall.shop.page.service.OssService;
|
||||||
import com.suisung.mall.shop.page.utis.VideoUtil;
|
import com.suisung.mall.shop.page.utis.VideoUtil;
|
||||||
@ -144,7 +145,7 @@ public class OssServiceImpl implements OssService {
|
|||||||
throw new ApiException(String.format(I18nUtil._("允许上传格式为:【%s】"), StringUtils.join(allowExtList, ",")));
|
throw new ApiException(String.format(I18nUtil._("允许上传格式为:【%s】"), StringUtils.join(allowExtList, ",")));
|
||||||
}
|
}
|
||||||
|
|
||||||
Map result = upload(file, user, dir, uploadPath, uploadName, fileName);
|
Map result = upload(file, user, dir, uploadPath, uploadName);
|
||||||
String url = (String) result.get("media_url");
|
String url = (String) result.get("media_url");
|
||||||
String thumb = (String) result.get("thumb");
|
String thumb = (String) result.get("thumb");
|
||||||
|
|
||||||
@ -173,7 +174,10 @@ public class OssServiceImpl implements OssService {
|
|||||||
* @param user 用户信息
|
* @param user 用户信息
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
public Map upload(MultipartFile file, UserDto user, String dir, String uploadPath, String uploadName, String fileName) {
|
public Map upload(MultipartFile file, UserDto user, String dir, String uploadPath, String uploadName) {
|
||||||
|
// 如果是图片,先压缩图片,再上传到 cos 对象存储
|
||||||
|
file = UploadUtil.compressImageIfNeeded(file, 2048);
|
||||||
|
|
||||||
// 创建临时文件
|
// 创建临时文件
|
||||||
creTempFile(file, dir, uploadName);
|
creTempFile(file, dir, uploadName);
|
||||||
// String localUrl = IP + "/admin/shop/static/image/" + dir + uploadName; // 文件本地路径
|
// String localUrl = IP + "/admin/shop/static/image/" + dir + uploadName; // 文件本地路径
|
||||||
@ -294,7 +298,7 @@ public class OssServiceImpl implements OssService {
|
|||||||
throw new ApiException(String.format(I18nUtil._("允许上传格式为:【%s】"), StringUtils.join(allowExtList, ",")));
|
throw new ApiException(String.format(I18nUtil._("允许上传格式为:【%s】"), StringUtils.join(allowExtList, ",")));
|
||||||
}
|
}
|
||||||
|
|
||||||
return upload(file, user, dir, uploadPath, uploadName, fileName);
|
return upload(file, user, dir, uploadPath, uploadName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user