springboot页面上传图片过大的后台解决办法-------------通过Thumbnails做图片压缩,图片格式转换------这一篇就够!
程序员文章站
2022-07-14 21:55:24
...
最近的未成年人保护在互联网也是一浪高过一浪,为了支持*的政策,对未成年人保护。我们的商城也做了个实名认证的功能。这个功能能够根据用户上传的身份证信息自动判定是否为未成年,进而做出相应的业务处理。
问题点1:在于我们使用的三方服务ocr接口限制文件传输为1M,也就是说你的图片过大,就会出现识别报错的问题。而现在的高像素手机,随便一拍就是几兆,必然要做图片压缩的处理。
问题点2:用户用的不同的手机,拍出来的照片,或者传输的照片的图片格式也是各式各样。但是三方服务接口就接受三种类型的图片。jpg,bmp,jpeg。没有办法。要么就是对别的类型在接口层控制住,提示用户格式不正确。要么处理图片的格式。
以上这就是本篇的业务场景,和要解决的问题点。
下面对上面的两个问题来做处理。 接口接受前端上传的照片:
代码分为三步:
- 首先接收到图片文件后进行压缩,转换图片类型。也是本节要解决的问题!
- 对图片进行Base64转码。这个是三方服务的接口要求。
- 调用业务层进行后续操作。
1.首先是引入依赖:
<!--图片压缩工具类thumbnailator-->
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.8</version>
</dependency>
2.然后就是代码部分。工具类
2.1 controller层的私有公共方法
/**
* [图片转换格式,压缩公共方法]
*
* @param multipartFile
* @return
* @throws IOException
*/
private MultipartFile getCompressFile(MultipartFile multipartFile) throws IOException {
List fileTypeList = new ArrayList();
fileTypeList.add(FILE_TYPE_IMAGE_EXT_JPG.getId());
fileTypeList.add(FILE_TYPE_IMAGE_EXT_BMP.getId());
fileTypeList.add(FILE_TYPE_IMAGE_EXT_JPEG.getId());
String filePath = FileUtil.getFileAbsolutePath("doc", "jpg");
LOGGER.info("缓存文件的绝对路径:" + filePath);
//图片压缩
return ImageUtil.compressFile(multipartFile, filePath, fileTypeList);
}
2.2 获取临时文件在服务器上的绝对路径的方法
import java.io.File;
import java.util.UUID;
/**
* 文件操作工具类
* @date 2019-11-09
* @author zhanglifeng
*/
public class FileUtil {
public static String getFileAbsolutePath(String filePath,String fileType){
StringBuilder sb =new StringBuilder();
String fileName = sb.append(UUID.randomUUID()).append(".").append(fileType).toString();
sb.setLength(0);
sb.append(FileUtil.class.getClassLoader().getResource("").getPath());
sb.append(filePath).append(File.separator).append(fileName);
String path = sb.toString().replaceAll("\\\\", "\\/");
return path;
}
}
2.3 压缩,转换图片类型的工具类
import net.coobird.thumbnailator.Thumbnails;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.List;
/**
* 获取图片尺寸和截图 工具类
*
* @author zhanglifeng
* @date 2019-11-08
*/
public class ImageUtil {
private final static Logger logger = LoggerFactory.getLogger(ImageUtil.class);
/**
* [压缩要上传的文件,并将文件类型转为指定的文件类型集合中的一个。]
*
* @param file 要上传的文件
* @param absolutePath 临时文件的绝对路径
* @param fileTypeList 文件转成的类型集合
* @return
*/
public static MultipartFile compressFile(MultipartFile file, String absolutePath, List<String> fileTypeList) throws IOException {
//记录原MultipartFile,如果压缩异常就用原来的MultipartFile
MultipartFile oldMultipartFile = file;
FileInputStream fileInputStream = null;
try {
String fileName = file.getName();
String originalFilename = file.getOriginalFilename();
String contentType = file.getContentType();
//获取要上传的文件后缀
String fileExt = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
File tempFile = new File(absolutePath);
if (fileTypeList.contains(fileExt)) {
//如果文件类型符合,则只压缩就好了
Thumbnails.of(file.getInputStream())
.scale(1f)
.outputQuality(0.2f)
.toFile(tempFile);
} else {
//如果文件类型不在指定的集合内。则要转格式,并压缩
Thumbnails.of(file.getInputStream())
.scale(1f)
.outputFormat(fileTypeList.get(0))
.outputQuality(0.2f)
.toFile(tempFile);
originalFilename = originalFilename.replace("." + fileExt, "." + fileTypeList.get(0));
}
fileInputStream = new FileInputStream(tempFile);
file = new MockMultipartFile(fileName, originalFilename, contentType, fileInputStream);
boolean success = tempFile.delete();
logger.info("删除临时file success:{}", success);
} catch (IOException e) {
logger.error("压缩图片失败,把MultipartFile赋值为原来的值oldFile,exception:{}", e);
file = oldMultipartFile;
} finally {
fileInputStream.close();
}
return file;
}
}
然后可以本地通过postman调用测试接口,可以先注释掉删除临时文件的代码。可以看到压缩后的文件才几十到几百kb.
并且png格式的图片变成jpg格式的。目标达成!
如果感觉图片压缩的太过或者还要在压缩。可以调整这个值:outputQuality(0.2f)
的大小。甚至可以一遍不行来两边。