springboot页面上传图片过大的后台解决办法-------------通过Thumbnails做图片压缩,图片格式转换------这一篇就够!

最近的未成年人保护在互联网也是一浪高过一浪,为了支持政府的政策,对未成年人保护。我们的商城也做了个实名认证的功能。这个功能能够根据用户上传的身份证信息自动判定是否为未成年,进而做出相应的业务处理。

问题点1:在于我们使用的三方服务ocr接口限制文件传输为1M,也就是说你的图片过大,就会出现识别报错的问题。而现在的高像素手机,随便一拍就是几兆,必然要做图片压缩的处理。

问题点2:用户用的不同的手机,拍出来的照片,或者传输的照片的图片格式也是各式各样。但是三方服务接口就接受三种类型的图片。jpg,bmp,jpeg。没有办法。要么就是对别的类型在接口层控制住,提示用户格式不正确。要么处理图片的格式。
以上这就是本篇的业务场景,和要解决的问题点。


下面对上面的两个问题来做处理。 接口接受前端上传的照片:

代码分为三步

  1. 首先接收到图片文件后进行压缩,转换图片类型。也是本节要解决的问题!
  2. 对图片进行Base64转码。这个是三方服务的接口要求。
  3. 调用业务层进行后续操作。
    在这里插入图片描述

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)的大小。甚至可以一遍不行来两边。

参考博文:
1.文件上传MultipartFile实现图片压缩

2.java后台对上传的图片进行压缩

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章