之前在学习MultipartFile时需要对文件上传的大小进行判断,但是在工作中,需要进一步的优化系统性能和资源利用率,对用户上传的文件需要进行压缩,这里就用到了Thumbnails工具类
注意MultipartFile类是spring的所有,必须是一个spring项目才可以使用。
引入Thumbnails依赖
<!--thumbnailator 压缩工具-->
<dependency>
<groupId>net.coobird</groupId>
<artifactId>thumbnailator</artifactId>
<version>0.4.8</version>
</dependency>
上传文件(controller层)
@ApiOperation(value = "文件上传")
@PostMapping("/uploadFile")
@ApiOperationSupport(author = "author")
public ActionResult<UploadResult> uploadFile(@RequestParam("file") MultipartFile file){
if (file.isEmpty()){
throw new ApplicationException(ErrorCodes.INVALID_ARGUMENTS,"请选择上传文件");
}
//上传成功返回完整路径的url
return AliyunOssClient.uploadFile(file);
}
处理文件(逻辑处理层)
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.PutObjectRequest;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.PostConstruct;
import java.io.File;
@Component
public class AliyunOssClient {
private static final Logger logger = LoggerFactory.getLogger(AliyunOssClient.class);
private static OSS ossClient;
private AliyunProperties aliyunProperties;
private static String bucketName;//表示目标存储桶的名称
private static String prefix; //前缀
private static String bizUrl; //网络访问url
@Autowired
public AliyunOssClient(AliyunProperties aliyunProperties) {
this.aliyunProperties = aliyunProperties;
}
//初始化
@PostConstruct
public void init() {
ossClient = new OSSClientBuilder().build(
aliyunProperties.getOssEndpointUrl(),
aliyunProperties.getAccessKeyId(),
aliyunProperties.getAccessKeySecret());
bizUrl = aliyunProperties.getOssBizUrl();
prefix = aliyunProperties.getOssBaseFolder() + "/";
bucketName = aliyunProperties.getOssBucketName();
}
public static ActionResult<UploadResult> uploadFile(MultipartFile multiFile) {
String fileName = multiFile.getOriginalFilename();
Assert.notNull(fileName, "文件上传失败:未获取到文件名称");
String suffix = fileName.substring(fileName.lastIndexOf("."));
try {
//创建一个临时文件,方法结束时自动清理文件
File tempFile = File.createTempFile("temp" + fileName.substring(0,fileName.lastIndexOf(".")), suffix);
long maxSize = 3*1024*1024;
// 检查文件大小是否超过指定的最大值
if (multiFile.getSize() > maxSize) {
// 进行压缩操作,将文件压缩至指定大小
tempFile = FileUtils.compress(multiFile);
} else {
//原文件返回
multiFile.transferTo(tempFile);
}
return upload(tempFile, "upload");
} catch (Exception e) {
return ActionResult.error(ErrorCodes.ILLEGAL_OPERATE, "文件上传失败:" + e.getMessage());
}
}
/**
* 上传成功返回完整路径的url
*/
public static ActionResult<UploadResult> upload(File file, String folderName) {
try {
String key = doUploadFile(file, bucketName, prefix, folderName);
UploadResult uploadResult = new UploadResult();
//文件网络地址
uploadResult.setSrc(bizUrl + "/" + key);
return ActionResult.ok(ErrorCodes.OK, uploadResult);
} catch (Exception e) {
return ActionResult.error(ErrorCodes.ILLEGAL_OPERATE, "文件上传失败:" + e.getMessage());
}
}
/**
* 上传aliyun-oos
* 返回key 表示要上传对象的键(key),它可以是文件名或对象在存储桶中的路径
*/
private static String doUploadFile(File file, String bucket, String prefixName, String folderName) {
if (StringUtils.isNotEmpty(folderName)) {
prefixName += folderName + "/";
}
String suffix = "";
String name = file.getName();
if (StringUtils.isNotEmpty(name)) {
suffix = "." + name.substring(name.lastIndexOf(".") + 1);
}
String key = prefixName + name.substring(0,name.lastIndexOf(".")) + suffix;
if (logger.isDebugEnabled()) {
logger.debug("AliOSS文件上传:{}", key);
}
ossClient.putObject(new PutObjectRequest(bucket, key, file));
return key;
}
}
注意:
PutObjectRequest
类是用于向Amazon S3存储桶中上传对象的请求类。该类的构造函数PutObjectRequest(String bucketName, String key, File file)
接受三个参数:bucketName
、key
和file
。
bucketName
是一个字符串,表示目标存储桶的名称。key
是一个字符串,表示要上传对象的键(key),它可以是文件名或对象在存储桶中的路径。file
是一个java.io.File
对象,表示要上传到存储桶的本地文件。
压缩文件(自定义工具类)
import net.coobird.thumbnailator.Thumbnails;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
public class FileUtils {
/**
* 压缩上传的图片
* @param multiFile 需要压缩的对象
* @return
*/
public static File compress(MultipartFile multiFile) throws IOException {
String fileName = multiFile.getOriginalFilename();
// 使用 .jpg 后缀,使用其他后缀Thumbnails工具有bug
String suffix = ".jpg";
String tempFileName = fileName.substring(0,fileName.lastIndexOf(".")) + "temp";
File tempFile = File.createTempFile(tempFileName, suffix);
try {
Thumbnails.of(multiFile.getInputStream())
.scale(1f)
.outputQuality(0.4f)
.toFile(tempFile);
} catch (IOException e) {
// 压缩失败就返回原来的图片
multiFile.transferTo(tempFile);
}
//返回压缩图片
return tempFile;
}
}
注意:Thumbnails工具是有缺陷的,Thumbnails.scale效果会导致图片大小变大
这里具体可以参考这篇(Thumbnails 压缩后反而变大_thumbnails.of(src).size_iiyuhz的博客-CSDN博客)非常感谢博主