You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot应用中如何实现图片大小校验与超限自动压缩?

在Spring Boot中实现图片上传的大小校验与自动压缩

一、基础配置:拦截超大请求

先通过Spring配置设置文件上传的基础阈值,避免容器直接拦截过大的请求:

spring:
  servlet:
    multipart:
      max-file-size: 50MB  # 单个文件最大允许值,按需调整
      max-request-size: 100MB  # 整个请求的总文件大小限制

二、自定义大小校验与压缩逻辑

1. 配置可调整的参数

创建配置类,把压缩阈值、目标尺寸等参数抽出来,方便后续修改:

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@Component
@ConfigurationProperties(prefix = "image.upload")
public class ImageUploadProperties {
    // 触发压缩的大小阈值(2MB)
    private long compressThreshold = 2 * 1024 * 1024;
    // 压缩后的目标宽度(按比例缩放高度)
    private int targetWidth = 1920;
    // 图片质量(0-1,值越高质量越好)
    private float quality = 0.7f;

    // getter、setter 省略
}

2. 实现图片压缩工具类

用Thumbnails库简化压缩逻辑,先在pom.xml添加依赖:

<dependency>
    <groupId>net.coobird</groupId>
    <artifactId>thumbnailator</artifactId>
    <version>0.4.19</version>
</dependency>

编写工具类,集成大小校验和压缩:

import net.coobird.thumbnailator.Thumbnails;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.io.File;
import java.io.InputStream;

@Component
public class ImageCompressUtil {

    private final ImageUploadProperties properties;

    public ImageCompressUtil(ImageUploadProperties properties) {
        this.properties = properties;
    }

    public MultipartFile processImage(MultipartFile file) throws IOException {
        // 大小未超过阈值,直接返回原文件
        if (file.getSize() <= properties.getCompressThreshold()) {
            return file;
        }

        // 执行压缩
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        Thumbnails.of(file.getInputStream())
                .size(properties.getTargetWidth(), Integer.MAX_VALUE) // 按宽度等比例缩放
                .outputQuality(properties.getQuality())
                .toOutputStream(outputStream);

        // 包装为MultipartFile返回
        return new CustomMultipartFile(file.getOriginalFilename(), file.getContentType(), outputStream.toByteArray());
    }

    // 自定义MultipartFile实现,用于包装压缩后的字节数据
    private static class CustomMultipartFile implements MultipartFile {
        private final String filename;
        private final String contentType;
        private final byte[] content;

        public CustomMultipartFile(String filename, String contentType, byte[] content) {
            this.filename = filename;
            this.contentType = contentType;
            this.content = content;
        }

        @Override
        public String getName() { return filename; }
        @Override
        public String getOriginalFilename() { return filename; }
        @Override
        public String getContentType() { return contentType; }
        @Override
        public boolean isEmpty() { return content.length == 0; }
        @Override
        public long getSize() { return content.length; }
        @Override
        public byte[] getBytes() { return content; }
        @Override
        public InputStream getInputStream() { return new ByteArrayInputStream(content); }
        @Override
        public void transferTo(File dest) throws IOException { Files.write(dest.toPath(), content); }
    }
}

3. 在Controller中集成

在上传接口里调用工具类,完成校验、压缩和后续业务处理:

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;

@RestController
public class ImageUploadController {

    private final ImageCompressUtil imageCompressUtil;

    public ImageUploadController(ImageCompressUtil imageCompressUtil) {
        this.imageCompressUtil = imageCompressUtil;
    }

    @PostMapping("/upload/image")
    public ResponseEntity<String> uploadImage(@RequestParam("file") MultipartFile file) throws IOException {
        // 校验是否为图片类型
        String contentType = file.getContentType();
        if (contentType == null || !contentType.startsWith("image/")) {
            return ResponseEntity.badRequest().body("仅支持上传图片类型文件");
        }

        // 处理图片:校验大小并压缩
        MultipartFile processedFile = imageCompressUtil.processImage(file);

        // 此处添加文件保存逻辑(如存本地、OSS等)
        // saveToStorage(processedFile);

        return ResponseEntity.ok(String.format("上传成功:原大小%.2fMB,处理后%.2fMB",
                file.getSize() / 1024.0 / 1024,
                processedFile.getSize() / 1024.0 / 1024));
    }
}

三、优化建议

  • 全局异常处理:捕获压缩时的IO异常、不支持的图片格式异常,返回标准化错误响应。
  • 格式适配:针对PNG、WebP等格式做特殊处理,比如保留PNG的透明度。
  • 异步处理:大图片压缩耗时较长时,用异步线程处理,避免阻塞请求线程。

内容的提问来源于stack exchange,提问作者Gaur 97

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 17:57:11