MultipartFile上传文件&Thumbnails图片压缩

之前在学习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)接受三个参数:bucketNamekeyfile

  • 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博客)非常感谢博主 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值