问题背景
服务器带宽有限,需要图片传给第三方进行业务处理,图片过大影响响应时间,需要进行压缩
具体实现
import net.coobird.thumbnailator.Thumbnails;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.compress.utils.IOUtils;
import org.springframework.util.StringUtils;
import java.io.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
/**
* @author : liuxinchi
* @date :2022/6/16 16:51
* @description : 图片工具类
*/
public class ImageUtils {
/**
* 根据图片的base64数据缩放图片20kb
*
* @param base64ImagStr 原图的base64字符换
* @param imageType 图片类型
* @return base64数据缩放图片
*/
public static String scaleImage(String base64ImagStr, String imageType, int targetSize) {
if (StringUtils.hasLength(base64ImagStr) && !"0".equals(base64ImagStr)) {
try {
byte[] imageBytes = Base64.decodeBase64(base64ImagStr);
ByteArrayInputStream imageStream = new ByteArrayInputStream(imageBytes);
ByteArrayOutputStream stream = new ByteArrayOutputStream();
Thumbnails.of(imageStream).scale(0.7).outputFormat(imageType).toOutputStream(stream);
String resultBase64Str = Base64.encodeBase64String(stream.toByteArray());
Integer imageSizeBase64 = imageSize(resultBase64Str);
if (imageSizeBase64 > targetSize) {
resultBase64Str = scaleImage(resultBase64Str, imageType, targetSize);
}
return resultBase64Str;
} catch (IOException e) {
e.printStackTrace();
}
}
return base64ImagStr;
}
/**
* 计算图片的大小,返回单位为KB
*
* @param imageBase64Str 图片base64数据
* @return 图片大小
*/
public static Integer imageSize(String imageBase64Str) {
//1.找到等号,把等号也去掉(=用来填充base64字符串长度用)
int equalIndex = imageBase64Str.indexOf("=");
if (imageBase64Str.indexOf("=") > 0) {
imageBase64Str = imageBase64Str.substring(0, equalIndex);
}
//2.原来的字符流大小,单位为字节
int strLength = imageBase64Str.length();
//3.计算后得到的文件流大小,单位为字节
int size = strLength - (strLength / 8) * 2;
return bytesToKB(size);
}
/**
* byte(字节)根据长度转成kb(千字节)
*
* @param bytes 字节
* @return 大小
*/
public static Integer bytesToKB(long bytes) {
BigDecimal filesize = new BigDecimal(bytes);
BigDecimal kilobyte = new BigDecimal(1024);
float returnValue = filesize.divide(kilobyte, 1, RoundingMode.DOWN).floatValue();
return (int) returnValue;
}
/**
* 图片压缩
* @param base64Str base46字符串
* @param targetSize 目标大小
* @return
* @throws IOException
*/
public static String pictureCompression(String base64Str, int targetSize) throws IOException {
Integer size = imageSize(base64Str);
if (size > targetSize) {
ByteArrayInputStream imageStream = new ByteArrayInputStream(Base64.decodeBase64(base64Str));
ByteArrayOutputStream stream = new ByteArrayOutputStream();
Thumbnails.of(imageStream).scale(1f).outputFormat("jpeg").toOutputStream(stream);
base64Str = Base64.encodeBase64String(stream.toByteArray());
Integer jpegSize = imageSize(base64Str);
if (jpegSize > targetSize) {
base64Str = scaleImage(base64Str, "jpeg", targetSize);
}
}
return base64Str;
}
public static void main(String[] args) throws Exception {
String base64Str = Base64.encodeBase64String(IOUtils.toByteArray(new FileInputStream("C:\\Users\\LIUXINCHI-A\\Pictures\\Saved Pictures\\20220607101728.jpg")));
base64Str = pictureCompression(base64Str, 100);
System.out.println(imageSize(base64Str));
}
}
引入maven依赖包
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.8</version>
</dependency>
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.6</version>
</dependency>