需要在原有项目中嵌套一个压缩的方法,接收MultipartFile,并返回MultipartFile,不影响原有方法的运行。压缩幅度很大。直接贴图看效果
第一步:添加maven依赖
<!--thumbnailator 压缩工具-->
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.8</version>
</dependency>
第二步,添加以下三个类
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* 公共 工具类
* Created by zxy on 18/11/15.
*/
public class ToolsUtil {
/**
* InputStream转换为byte[]
*
* @param inStream
* @return
* @throws IOException
*/
public static final byte[] getByteArray(InputStream inStream) throws IOException {
ByteArrayOutputStream swapStream = new ByteArrayOutputStream();
byte[] buff = new byte[100];
int rc = 0;
while ((rc = inStream.read(buff, 0, 100)) > 0) {
swapStream.write(buff, 0, rc);
}
byte[] in2b = swapStream.toByteArray();
return in2b;
}
}
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
public 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() {
// TODO - implementation depends on your requirements
return System.currentTimeMillis() + Math.random() + "." + header.split("/")[1];
}
@Override
public String getOriginalFilename() {
// TODO - implementation depends on your requirements
return System.currentTimeMillis() + (int)Math.random() * 10000 + "." + header.split("/")[1];
}
@Override
public String getContentType() {
// TODO - implementation depends on your requirements
return header.split(":")[1];
}
@Override
public boolean isEmpty() {
return imgContent == null || imgContent.length == 0;
}
@Override
public long getSize() {
return imgContent.length;
}
@Override
public byte[] getBytes() throws IOException {
return imgContent;
}
@Override
public InputStream getInputStream() throws IOException {
return new ByteArrayInputStream(imgContent);
}
@Override
public void transferTo(File dest) throws IOException, IllegalStateException {
new FileOutputStream(dest).write(imgContent);
}
}
/**
* 获取图片尺寸和截图 工具类
*
* @author zhangxiaoyan
*/
public class ImageSizeUtil {
private final static Logger logger = LoggerFactory.getLogger(ImageSizeUtil.class);
/**
* 获取图片最长边长度
* @param params
* @return
*/
public static int getImageLengthOfSide(MultipartFile params){
int lengthSize = 0;
Map<String, Integer> result = new HashMap<>();
long beginTime = new Date().getTime();
// 获取图片格式
String suffixName = getSuffixNameInfo(params);
try {
Iterator<ImageReader> readers = ImageIO.getImageReadersByFormatName(suffixName);
ImageReader reader = (ImageReader) readers.next();
ImageInputStream iis = ImageIO.createImageInputStream(params.getInputStream());
reader.setInput(iis, true);
result.put("width",reader.getWidth(0));
result.put("height",reader.getHeight(0));
if(reader.getWidth(0) > reader.getHeight(0)){
lengthSize = reader.getWidth(0);
}else{
lengthSize = reader.getHeight(0);
}
} catch (IOException e) {
e.printStackTrace();
}
return lengthSize;
}
/**
* 获取图片格式
* @param params
* @return
*/
public static String getSuffixNameInfo(MultipartFile params){
String result = "";
// 图片后缀
String suffixName = params.getOriginalFilename().substring(
params.getOriginalFilename().lastIndexOf("."));
if(suffixName.indexOf("png")>0){
result = "png";
}else if(suffixName.indexOf("jpg")>0){
result = "jpg";
}else if(suffixName.indexOf("jpeg")>0){
result = "jpeg";
}
return result;
}
/**
* 根据指定大小压缩图片
*
* @param imageBytes 源图片字节数组
* @param desFileSize 指定图片大小,单位kb
* @return 压缩质量后的图片字节数组
*/
public static byte[] compressPicForScale(byte[] imageBytes, long desFileSize) {
if (imageBytes == null || imageBytes.length <= 0 || imageBytes.length < desFileSize * 1024) {
return imageBytes;
}
long srcSize = imageBytes.length;
double accuracy = getAccuracy(srcSize / 1024);
// double accuracy = 0.85;
try {
while (imageBytes.length > desFileSize * 1024) {
ByteArrayInputStream inputStream = new ByteArrayInputStream(imageBytes);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(imageBytes.length);
Thumbnails.of(inputStream)
.scale(accuracy)
.outputQuality(accuracy)
.toOutputStream(outputStream);
imageBytes = outputStream.toByteArray();
}
logger.info("【图片压缩】imageId={} | 图片原大小={}kb | 压缩后大小={}kb",
"", srcSize / 1024, imageBytes.length / 1024);
} catch (Exception e) {
logger.error("【图片压缩】msg=图片压缩失败!", e);
}
return imageBytes;
}
/**
* 自动调节精度(经验数值)
*
* @param size 源图片大小,单位kb
* @return 图片压缩质量比
*/
private static double getAccuracy(long size) {
double accuracy;
if (size < 900) {
accuracy = 0.85;
} else if (size < 2047) {
// accuracy = 0.6;
accuracy = 0.8;
} else if (size < 3275) {
// accuracy = 0.44;
accuracy = 0.7;
} else {
accuracy = 0.4;
}
return accuracy;
}
/**
* base64 转MultipartFile
* @param base64
* @return
*/
public static MultipartFile base64ToMultipart(String base64) {
try {
// 注意base64是否有头信息,如:data:image/jpeg;base64,。。。
String[] baseStrs = base64.split(",");
BASE64Decoder decoder = new BASE64Decoder();
byte[] b = new byte[0];
b = decoder.decodeBuffer(baseStrs[1]);
for(int i = 0; i < b.length; ++i) {
if (b[i] < 0) {
b[i] += 256;
}
}
return new BASE64DecodedMultipartFile(b, baseStrs[0]);
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
/**
* 压缩图片
* @return
*/
public static MultipartFile byte2Base64StringFun(MultipartFile fileImg){
MultipartFile result = fileImg;
// 获取图片最长边
int imageLengthSize = ImageSizeUtil.getImageLengthOfSide(fileImg);
Long swd = fileImg.getSize();
BASE64Encoder encoder = new BASE64Encoder();
String imgData1 = null;
try {
InputStream inputStream = fileImg.getInputStream();
byte[] imgData = ImageSizeUtil.compressPicForScale(ToolsUtil.getByteArray(inputStream),2000);
imgData1 = "data:"+fileImg.getContentType()+";base64,"+encoder.encode(imgData);
MultipartFile def = ImageSizeUtil.base64ToMultipart(imgData1);
result = def;
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
}
调用byte2Base64StringFun()即可