Files
FrameTour-BE/src/main/java/com/ycwl/basic/utils/ImageUtils.java
Jerry Yan f885f734ad perf(viid):优化线程池配置与图片裁剪内存管理
- 调整线程池核心线程数为8,最大线程数为32,空闲时间10秒- 队列大小从1024降至100,提升响应速度
- 添加CallerRunsPolicy策略,防止任务丢失
- 图片裁剪方法增加try-finally块确保资源释放- 显式调用image.flush()和System.gc()优化内存使用
- ByteArrayOutputStream关闭操作添加异常捕获
-修复潜在的内存泄漏问题
2025-09-27 13:17:48 +08:00

133 lines
4.0 KiB
Java

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);
}
}
}