package com.ruoyi.web.controller.tool; import cn.hutool.core.util.StrUtil; import com.ruoyi.common.utils.file.FileUploadUtils; import lombok.extern.slf4j.Slf4j; import org.springframework.util.StringUtils; import org.springframework.web.multipart.MultipartFile; import java.io.*; @Slf4j public class FaceBase64ToUrlUtil { /** * 处理访客人像(Base64转URL) * 使用若依的 FileUploadUtils,返回完整URL * * @param faceImageData Base64图片数据 * @param idCard 身份证号(用于生成文件名) * @return 图片完整URL */ public static String processFaceImage(String faceImageData, String idCard) { if (!StringUtils.hasText(faceImageData)) { return null; } try { // 判断是否为Base64格式 if (isBase64Image(faceImageData)) { // 1. Base64转MultipartFile MultipartFile file = base64ToMultipartFile(faceImageData, "face_" + idCard); if (file == null) { log.error("Base64转文件失败"); return null; } // 2. 使用若依的FileUploadUtils上传,返回完整URL String imageUrl = FileUploadUtils.upload(file); log.info("访客人像上传成功,URL: {}", imageUrl); return imageUrl; } else { // 如果已经是URL,直接返回 log.info("访客人像已是URL格式,直接使用: {}", faceImageData); return faceImageData; } } catch (Exception e) { log.error("处理访客人像失败,身份证号: {}", idCard, e); return null; } } /** * 判断是否为Base64图片格式 */ private static boolean isBase64Image(String data) { if (!StringUtils.hasText(data)) { return false; } return data.contains("data:image/") || data.contains("base64") || (data.length() > 100 && !data.startsWith("http")); } /** * Base64转MultipartFile */ private static MultipartFile base64ToMultipartFile(String base64Data, String fileName) { try { // 去除Base64前缀 String[] base64Array = base64Data.split(","); String base64Str = base64Array.length > 1 ? base64Array[1] : base64Array[0]; // 获取图片格式 String imageType = getImageType(base64Data); if (StrUtil.isBlank(imageType)) { imageType = "jpg"; } // 解码Base64 byte[] imageBytes = cn.hutool.core.codec.Base64.decode(base64Str); // 创建临时文件 String fullFileName = fileName + "." + imageType; File tempFile = File.createTempFile("upload_", "_" + fullFileName); tempFile.deleteOnExit(); // 写入数据 try (FileOutputStream fos = new FileOutputStream(tempFile)) { fos.write(imageBytes); fos.flush(); } // 转换为MultipartFile return new CustomMultipartFile(tempFile, fullFileName); } catch (Exception e) { log.error("Base64转MultipartFile失败", e); return null; } } /** * 获取图片格式 */ private static String getImageType(String base64Data) { if (StrUtil.isBlank(base64Data)) { return "jpg"; } if (base64Data.contains("data:image/")) { String prefix = base64Data.substring(0, base64Data.indexOf(",")); if (prefix.contains("png")) { return "png"; } else if (prefix.contains("jpg") || prefix.contains("jpeg")) { return "jpg"; } else if (prefix.contains("gif")) { return "gif"; } else if (prefix.contains("bmp")) { return "bmp"; } else if (prefix.contains("webp")) { return "webp"; } } return "jpg"; } /** * 自定义MultipartFile实现 */ public static class CustomMultipartFile implements MultipartFile { private final File file; private final String fileName; public CustomMultipartFile(File file, String fileName) { this.file = file; this.fileName = fileName; } @Override public String getName() { return fileName; } @Override public String getOriginalFilename() { return fileName; } @Override public String getContentType() { String extension = getFileExtension(fileName); switch (extension) { case "png": return "image/png"; case "jpg": case "jpeg": return "image/jpeg"; case "gif": return "image/gif"; case "bmp": return "image/bmp"; case "webp": return "image/webp"; default: return "image/jpeg"; } } @Override public boolean isEmpty() { return file == null || file.length() == 0; } @Override public long getSize() { return file.length(); } @Override public byte[] getBytes() throws IOException { byte[] bytes = new byte[(int) file.length()]; try (FileInputStream fis = new FileInputStream(file)) { fis.read(bytes); } return bytes; } @Override public InputStream getInputStream() throws IOException { return new FileInputStream(file); } @Override public void transferTo(File dest) throws IOException, IllegalStateException { try (FileInputStream fis = new FileInputStream(file); FileOutputStream fos = new FileOutputStream(dest)) { byte[] buffer = new byte[1024]; int length; while ((length = fis.read(buffer)) > 0) { fos.write(buffer, 0, length); } fos.flush(); } } private String getFileExtension(String fileName) { if (fileName == null || fileName.isEmpty()) { return ""; } int lastDotIndex = fileName.lastIndexOf("."); if (lastDotIndex > 0 && lastDotIndex < fileName.length() - 1) { return fileName.substring(lastDotIndex + 1).toLowerCase(); } return ""; } } }