package com.ycwl.basic.utils; import cn.hutool.core.codec.Base64; import lombok.extern.slf4j.Slf4j; import org.springframework.web.multipart.MultipartFile; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; @Slf4j public class ImageUtils { public static MultipartFile base64ToMultipartFile(String base64) { String[] baseStrs = base64.split(","); byte[] b; b = Base64.decode(baseStrs[0]); for (int i = 0; i < b.length; ++i) { if (b[i] < 0) { b[i] += (byte) 256; } } return new Base64DecodedMultipartFile(b, baseStrs[0]); } public static MultipartFile cropImage(MultipartFile file, int x, int y, int w, int h) throws IOException { BufferedImage image = null; BufferedImage targetImage = null; ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { image = ImageIO.read(file.getInputStream()); log.info("图片宽高:{}", image.getWidth() + "x" + image.getHeight()); log.info("图片裁切:{}@{}", w + "x" + h, x + "," + y); if (image.getWidth() < w) { w = image.getWidth(); } if (image.getHeight() < h) { h = image.getHeight(); } int targetX = x; if (x < 0) { targetX = 0; } else if ((x + w) > image.getWidth()) { targetX = image.getWidth() - w; } int targetY = y; if (y < 0) { targetY = 0; } else if ((y + h) > image.getHeight()) { targetY = image.getHeight() - h; } log.info("图片实际裁切:{}@{}", w + "x" + h, targetX + "," + targetY); targetImage = image.getSubimage(targetX, targetY, w, h); ImageIO.write(targetImage, "jpg", baos); return new Base64DecodedMultipartFile(baos.toByteArray(), "image/jpeg"); } finally { // 修复内存泄漏:显式释放图片资源 if (image != null) { image.flush(); image = null; } if (targetImage != null) { targetImage.flush(); targetImage = null; } try { baos.close(); } catch (IOException e) { log.warn("关闭ByteArrayOutputStream失败", e); } // 建议JVM进行垃圾回收 System.gc(); } } public static class Base64DecodedMultipartFile implements MultipartFile { private final byte[] imgContent; private final String header; public Base64DecodedMultipartFile(byte[] imgContent, String header) { this.imgContent = imgContent; this.header = header.split(";")[0]; } @Override public String getName() { return System.currentTimeMillis() + Math.random() + "." + header.split("/")[1]; } @Override public String getOriginalFilename() { return System.currentTimeMillis() + "." + header.split("/")[1]; } @Override public String getContentType() { return ""; } @Override public boolean isEmpty() { return imgContent == null || imgContent.length == 0; } @Override public long getSize() { return imgContent.length; } @Override public byte[] getBytes() { return imgContent; } @Override public InputStream getInputStream() { return new ByteArrayInputStream(imgContent); } @Override public void transferTo(File dest) throws IOException, IllegalStateException { new FileOutputStream(dest).write(imgContent); } } }