前言:
- 压缩时间较长, 5M左右的图片压缩至500k左右大概需要2秒左右;
- Demo中返回base64字符串, 可根据自己需求改返回值类型;
环境:
注意:
- 本人只测试了两种类型的图片(jpg/png),其他类型还需自行测试;
- png类型的图片有点特殊,只能用另个开源组件进行压缩;
具体请看代码:
<!-- 处理除png以外的图片 -->
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.8</version>
</dependency>
<!-- 处理png类型的图片 -->
<dependency>
<groupId>org.jpedal</groupId>
<artifactId>OpenViewerFX</artifactId>
<version>6.6.14</version>
</dependency>
import com.idrsolutions.image.png.PngCompressor;
import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails;
import org.springframework.web.multipart.MultipartFile;
import sun.misc.BASE64Decoder;
import java.io.*;
import java.util.Base64;
import java.util.Optional;
/**
* 图片工具类
*/
@Slf4j
public class ImageUtil {
/**
* 压缩图片,返回base64字符串
* 接收MultipartFile格式文件;
* @param multipartFile
* @return
* @throws Exception
*/
public static String compressImageByMultipartFile(MultipartFile multipartFile) throws Exception {
File sourceFile = MultipartFileToFile(multipartFile);
return compressImageByFile(sourceFile);
}
/**
* 将MultipartFile转换为File
*/
public static File MultipartFileToFile(MultipartFile multiFile) throws IOException {
String fileName = multiFile.getOriginalFilename();
String prefix = fileName.substring(fileName.lastIndexOf("."));
InputStream in = null;
OutputStream out = null;
try {
File file = File.createTempFile(fileName, prefix);
out = new FileOutputStream(file);
in = multiFile.getInputStream();
int read = 0;
byte[] buffer = new byte[1024];
while ((read = in.read(buffer, 0, 1024)) != -1) {
out.write(buffer, 0, read);
}
return file;
} catch (Exception e) {
throw e;
}finally {
if (in != null){
in.close();
}
if (out != null){
out.close();
}
}
}
/**
* 压缩jpg图片,返回base64字符串
* sourceFile: 源文件;
*/
public static String compressImageByFile(File sourceFile) throws Exception {
log.info("原文件大小:[{}]",sourceFile.length());
InputStream in = null;
ByteArrayOutputStream out = null;
try {
//大于500K进行压缩:
if (sourceFile.length() > 500 * 1024) {
String fileName = sourceFile.getName();
String prefix = fileName.substring(fileName.lastIndexOf(".")+1);
if ("png".equals(prefix.toLowerCase())){
PngCompressor.compress(sourceFile,sourceFile);
}else {
//sourceFile = getCompressFile(sourceFile,0.15f);
Thumbnails.of(sourceFile).scale(1f).outputQuality(0.1f).toFile(sourceFile);
}
log.info("文件格式:[{}] -- 压缩后文件大小:[{}]",prefix,sourceFile.length());
}
in = new FileInputStream(sourceFile);
out = new ByteArrayOutputStream();
int read = 0;
byte[] buffer = new byte[1024];
while ((read = in.read(buffer, 0, 1024)) != -1) {
out.write(buffer, 0, read);
}
return Base64.getEncoder().encodeToString(out.toByteArray());
} catch (IOException e) {
throw e;
} finally {
if (in != null) {
in.close();
}
if (out != null){
out.close();
}
}
}
/**
* 如果接口超时时间允许,也可以递归处理压缩,以至于达到最理想的压缩大小;
* @param file
* @param quality
* @return
* @throws IOException
*/
private static File getCompressFile(File file,float quality) throws IOException {
Thumbnails.of(file).scale(1f).outputQuality(quality).toFile(file);
if(quality <= 0.1f || file.length() <= 500 * 1024){
return file;
}else{
quality = quality - 0.05f;
return getCompressFile(file,quality);
}
}
}
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
@RestController
public class ImageDemoController {
/** main方法测试 */
public static void main(String[] args) {
try {
File file = new File("C:/原图片.jpg");
String s = ImageUtil.compressImageByFile(file);
System.out.println("压缩后图片的base64字符串::" + s);
} catch (Exception ex) {
ex.printStackTrace();
}
}
/** 项目中测试 */
@PostMapping("/test/compressImage")
public String compressImage(MultipartFile file){
try {
String s = ImageUtil.compressImageByMultipartFile(file);
System.out.println("压缩后图片的base64字符串::" + s);
} catch (Exception ex) {
ex.printStackTrace();
}
return "成功";
}
}
|