在之前的项目中实现了通过minio实现对文件、图片的存储。在本篇文章中添加了通过thumbnailator预先实现图片压缩再上传至minio。(因为现在手机拍照的像素太高了!!每张照片动则近10M的大小,图片显示太慢啦!!!,所以尝试使用图片压缩来解决图片显示慢的问题)
以下是实现步骤
1、引入maven依赖
<!-- thumbnailator依赖 -->
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.8</version>
</dependency>
2、前置准备
由于我们项目中都是写一个统一的文件上传接口,也就是图片、文件等内容都是通过同一个接口上传的,但是我们只想要对图片进行压缩处理,所以得写一个判断方法,判断传入的参数是否为图片
/**
* 判断文件是否为图片
*/
public boolean isPicture(String imgName) {
boolean flag = false;
if (StringUtils.isBlank(imgName)) {
return false;
}
String[] arr = {"bmp", "dib", "gif", "jfif", "jpe", "jpeg", "jpg", "png", "tif", "tiff", "ico"};
for (String item : arr) {
if (item.equals(imgName)) {
flag = true;
break;
}
}
return flag;
}
3、业务逻辑层处理
具体的业务逻辑实现步骤我都以注释的形式写到了方法块中~包括了minio实现文件上传的步骤,方便大家理解!
public String fileUpload(MultipartFile multipartFile) {
try {
// 创建一个Minio的客户端对象
MinioClient minioClient = MinioClient.builder()
.endpoint(minioProperties.getEndpointUrl())
.credentials(minioProperties.getAccessKey(), minioProperties.getSecreKey())
.build();
// 判断桶是否存在
boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(minioProperties.getBucketName()).build());
if (!found) { // 如果不存在,那么此时就创建一个新的桶
minioClient.makeBucket(MakeBucketArgs.builder().bucket(minioProperties.getBucketName()).build());
} else { // 如果存在打印信息
System.out.println("Bucket 'spzx-bucket' already exists.");
}
// 设置存储对象名称
String dateDir = DateUtil.format(new Date(), "yyyyMMdd");
String uuid = UUID.randomUUID().toString().replace("-", "");
String suffix = multipartFile.getOriginalFilename().substring(multipartFile.getOriginalFilename().lastIndexOf(".") + 1);
String fileName = dateDir + "/" + uuid + multipartFile.getOriginalFilename();
System.out.println(fileName);
// 判断是否是图片并且大小超过100k
if (isPicture(suffix) && multipartFile.getSize() > (1024 * 1024 * 0.1)) {
// 缩放并调整图片质量
//创建一个字节数组输出流,用来存储处理后的图片数据
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
double quality = 1.0;
//根据上传图片的大小设置不同的压缩质量
if (multipartFile.getSize() <= (1024 * 1024)) {
quality = 0.3;
} else if (multipartFile.getSize() <= (1024 * 1024 * 2)) {
quality = 0.2;
} else {
quality = 0.1;
}
Thumbnails.of(multipartFile.getInputStream())
.scale(1f)//1f表示不改变图片的尺寸,保持原始大小
.outputQuality(quality)//根据设置的质量参数进行压缩处理
.toOutputStream(outputStream);//将处理之后的图片数据输出到字节数组输出流中
InputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray());
// 上传文件到MinIO
PutObjectArgs putObjectArgs = PutObjectArgs.builder()
.bucket(minioProperties.getBucketName())
.stream(inputStream, outputStream.size(), -1)
.object(fileName)
.build();
minioClient.putObject(putObjectArgs);
}
else{
PutObjectArgs putObjectArgs = PutObjectArgs.builder()
.bucket(minioProperties.getBucketName())
.stream(multipartFile.getInputStream(), multipartFile.getSize(), -1)
.object(fileName)
.build();
minioClient.putObject(putObjectArgs) ;
}
return minioProperties.getEndpointUrl() + "/" + minioProperties.getBucketName() + "/" + fileName;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
4、测试
这里我上传了一张原图大小为652KB的图片,经测试通过thumbnailator压缩之后上传到minio保存的大小约为64KB,按照业务逻辑就是压缩到了它原来大小的0.1倍
5、总结
这里我只实现了图片的压缩,其实还可以加水印旋转等处理,剩下的等我下次有需求实现了再更新吧!(附上一些thumbnailator的用法)
(1)size(宽度、高度) ----指定大小比例进行缩放(考虑图片完整度)
(2)scale(比例)----按照比例缩放0-1f
(3)rotate(90)----旋转90度
(4)sourceRegion(Positions.CENTER, 400,400) .size(200,200).keepAspectRatio(false) ----剪切
(5)watermark(Positions.CENTER) ----加水印
注:具体用法还是去参照官网吧~写博客就是为了共勉,希望大家喜欢