Java后端图片压缩,批量处理MultipartFile图片流,并压缩到指定大小,返回base64

拿图片不得大于1M为例,代码如下:

 
@PostMapping("upload")
    public void upload(@RequestParam("images") List<MultipartFile> files) throws IOException {
        // 处理files
        for (int i = 0; i < files.size(); i++) {
            MultipartFile file = files.get(i);
            // 保存文件到服务器或处理文件
            System.out.println(file.getOriginalFilename());
            String base64 = Base64ToCompressedImage.processImage(file);
            System.out.println(base64);
        }
        ...
        ...
    }
    // 图片不得大于1MB
    private static final int MAX_SIZE_BYTES = 1024 * 1024;
    // 初始压缩质量设为0.75
    private static final float quality = 0.75f;

    public static String processImage(MultipartFile file) throws IOException {
        // 读取MultipartFile到BufferedImage
        BufferedImage image = ImageIO.read(file.getInputStream());
        if (image == null) {
            throw new IOException("Invalid image format");
        }

        // 检查原始图片大小
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ImageIO.write(image, "jpg", baos); // 假设我们总是转换为JPG来压缩(如果需要)
        byte[] originalBytes = baos.toByteArray();
        if (originalBytes.length <= MAX_SIZE_BYTES) {
            // 图片大小已经符合要求,直接转换为Base64
            return Base64.getEncoder().encodeToString(originalBytes);
        }

        // 图片需要压缩
        return compressImageAndConvertToBase64(image, quality);
    }

    private static String compressImageAndConvertToBase64(BufferedImage image, float initialQuality) throws IOException {
        // JPEG图片格式
        String formatName = "JPEG";

        // 获取能写入JPEG格式的ImageWriter
        Iterator<ImageWriter> writers = ImageIO.getImageWritersByFormatName(formatName);
        if (!writers.hasNext()) {
            throw new IllegalStateException("No writers are found");
        }

        ImageWriter writer = writers.next();
        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        try (ImageOutputStream ios = ImageIO.createImageOutputStream(baos)) {
            writer.setOutput(ios);

            ImageWriteParam param = writer.getDefaultWriteParam();
            if (param.canWriteCompressed()) {
                param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT);

                float quality = initialQuality;

                while (true) {
                    param.setCompressionQuality(quality);

                    IIOImage iioImage = new IIOImage(image, null, null);
                    writer.write(null, iioImage, param);

                    if (baos.size() <= MAX_SIZE_BYTES) {
                        return Base64.getEncoder().encodeToString(baos.toByteArray());
                    } else if (quality > 0.1f) {
                        quality -= 0.1f;
                        baos.reset(); // 重置ByteArrayOutputStream
                    } else {
                        throw new IOException("Image could not be compressed to under 1MB even at minimum quality.");
                    }
                }
            } else {
                throw new IllegalStateException("Compression not supported.");
            }
        } finally {
            writer.dispose();
        }
    }

MAX_SIZE_BYTES:图片最大大小

quality :图片初始压缩质量

以上就是图片压缩的过程,亲测好用!

  • 6
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值