Java使用Minio实现图片上传

本文记录了一个SpringBoot项目中使用Minio作为图床服务器进行图片上传的过程。首先在Gradle中添加Minio依赖,然后通过Nacos配置中心获取参数初始化MinioClient。在MinioUtils类中实现了上传文件到指定桶的功能,确保桶存在或新建。在Controller层编写接口,接收前端文件并转换为所需参数,利用时间戳避免文件名冲突,上传成功返回图片URL。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最近项目中使用Minio图床服务器实现图片上传,在此做一个记录,项目中的环境如下:
Nacos、Gradle、springBoot、mybatis、MySQL…

首先,需要在Gradle中添加Minio的依赖,此项目中使用的是3.0.10版本

compile 'io.minio:minio:3.0.10'

然后在项目中添加MinioUtils的配置类,旨在调用Minio的服务,提供调用Minio上传图片的接口,项目中所需参数都写在了Nacos配置中心,因此使用@NacosValue的注解形式从Nacos配置文件中拿取对应的参数,调用上传图片的接口,返回一个 Minio域名/桶名/存入桶中的文件名 的url

import com.alibaba.nacos.api.config.annotation.NacosValue;
import com.iid.common.helper.IdHelper;
import io.minio.MinioClient;
import io.minio.errors.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.xmlpull.v1.XmlPullParserException;

import javax.annotation.PostConstruct;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

/**
 * @ClassName MinioUtils
 * @Description: TODO
 * @Author XuJianSong
 * @Date 2021-01-07
 * @Version V1.0
 **/
@Slf4j
@Component
public class MinioUtils {
    private MinioClient minioClient;
    @NacosValue(value = "${ymukj.minio.endpoint}")
    private String endPoint;//Minio的域名
    @NacosValue(value = "${ymukj.minio.accessKey}")
    private String accessKey;//Minio登录名
    @NacosValue(value = "${ymukj.minio.secretKey}")
    private String secretKey;//Minio登陆密码
    @NacosValue(value = "${ymukj.minio.preUrl}")
    private String preUrl;//图床图片的域名(带bucket的)

    @PostConstruct
    public void initMinioClient() {//调用Minio服务
        try {
            minioClient = new MinioClient(endPoint, accessKey, secretKey);
        } catch (InvalidEndpointException e) {
            log.error(e.getMessage(), e);
        } catch (InvalidPortException e) {
            log.error(e.getMessage(), e);
        }
    }

    public String uploadFile(String bucketName, String objName, InputStream inputStream, Long lenght, String contentType) {
        // 使用putObject上传一个文件到存储桶中。
        try {
            minioClient.putObject(bucketName, objName, inputStream, lenght, contentType);
            boolean isExist = minioClient.bucketExists(bucketName);
            if (!isExist) {
                minioClient.makeBucket(bucketName);
            }
            return preUrl+"/"+objName;
        } catch (Exception e) {
            e.printStackTrace();
            log.info(">>>>>>>>>>>>>>>>>>>>>>>>>Error:" + e);
            return null;
        }
    }
}

在Minio中是有“桶(bucket)”的概念的,所谓的桶,就是在Minio的图床上的文件夹,如果传参的桶名称在图床上已存在,上传的图片就会存入当前桶中;
如果传参的桶名称在图床上不存在,源码方法中会先创建桶,再存入

在这里插入图片描述

如图所示:左边的就是Minio图床中的桶,右边就是桶中的文件,Minio是支持上传所有文件的,视频、文档文件都可以,不过项目中没有涉及到这些功能,待后续再研究

接下来就是在项目中写上传图片的接口了,因为不涉及的数据库的操作,所以我直接在controller层中把接口全部写完了,没有再去调用service层的方法
Controller层接口接收前端的文件传参,再根据MinioUtils配置类中,上传图片的方法接收参数的要求,对文件进行处理,首先我们能看到MinioUtils配置文件中的上传图片接口要求接收的参数是bucket, objName, inputStream, lenght, contentType这四个,这四个参数分别是:桶名、上传并保存到桶的文件名,文件的输入流,文件的类型。上传成功的话会返回一个url,将这个url放到浏览器中可以直接打开这个图片,项目中如果需要使用这张图片,可以直接将这个url存入到数据库中,后面可以从数据库中直接取用

public GlobalResponse uploadPic(MultipartFile file) {
    String bucket = "pic";
    String filename = file.getOriginalFilename();
    String[] exts = filename.split("\\.");
    String ext = exts[exts.length - 1];
    String caselsh = filename.substring(0,filename.lastIndexOf("."));
    String objName = SystemHelper.now() + caselsh + "." + ext;
    log.info(">>>>>>>>>>>>>>>>>>>>>>>>>>objName:" + objName);
    String contentType = file.getContentType();
    InputStream inputStream = null;
    Long lenght = null;
    try {
        inputStream = file.getInputStream();
        lenght = Long.valueOf(inputStream.available());
    } catch (IOException e) {
        e.printStackTrace();
    }
    String picUrl = minioUtils.uploadFile(bucket, objName, inputStream, lenght, contentType);
    log.info(">>>>>>>>>>>>>>>>>>>>>>>>>>picUrl:" + picUrl);
    return GlobalResponse.success(picUrl);
}

这里需要注意的是上传到桶的文件名不要重复!不要重复!不要重复!
因为重复的文件名会导致一个问题:比如先上传一个图片A.png,存到桶中的名称是111.png,那么Minio域名/桶名/111.png就能直接打开文件A.png这张图,但是再上传一个图片B.png,存到同种的名称仍然是111.png,那么Minio域名/桶名/111.png打开的就是B.png这张图,如果图片A.png已经存入数据库,并已经使用的话,后果可想而知。
因此接口中使用的解决方案是,使用时间戳+文件原名称+后缀的形式来命名,因为时间戳是13位毫秒级的,因此就算是上传同名的文件,也不会有存到桶中的文件名会重复的问题

本次的分享就到这里,如有错误欢迎大家来指正!

<think>好的,我现在需要帮助用户在Java实现将压缩后的图片上传MinIO服务器。用户的问题涉及文件压缩和解压,以及如何与MinIO集成。让我先理清楚用户的需求和可能的解决步骤。 首先,用户提到之前有关于解压GZIP文件并上传到MinIO的引用内容,以及如何控制文件上传大小限制的设置。现在用户想处理的是压缩后的图片上传,可能是指已经压缩过的图片文件(比如JPEG压缩)或者需要先压缩再上传。需要明确的是,用户是否需要在Java中进行图片压缩处理,还是直接上传已压缩的图片? 根据用户的问题描述,“压缩后的图像文件”可能指的是已经压缩好的图片,比如通过某种方式(如使用ImageIO或第三方库)压缩后的JPEG或PNG文件。用户需要将这些文件上传到MinIO。因此,步骤可能包括:压缩图片、配置MinIO客户端、处理上传大小限制、执行上传操作。 首先,图片压缩部分。Java中常用的图片处理库有ImageIO,但功能有限,可能无法进行高级压缩。可能需要使用第三方库如Thumbnailator或Apache Commons Imaging来实现图片的尺寸调整和质量压缩。例如,使用BufferedImage和ImageWriter设置压缩质量参数。 然后,MinIO上传部分。需要引入MinIOJava客户端库,创建MinioClient实例,并确保连接到正确的端点、访问密钥和密钥。上传文件可以使用putObject方法,指定桶名称、对象名称、文件路径和内容类型。 另外,用户之前的问题提到上传GZIP文件时解压,而这次是上传压缩后的图片,所以不需要解压,直接上传即可。但需要注意文件大小限制,引用[2]中提到需要设置max-file-size和max-request-size,这可能是在Spring Boot应用中通过配置文件调整,比如在application.yml中设置multipart.max-file-size和max-request-size。如果用户的应用是基于Spring Boot的文件上传,需要确保这些配置正确,避免上传大文件时失败。 可能的步骤总结: 1. 压缩图片:使用Java图像处理库对图片进行压缩。 2. 配置MinIO客户端:正确初始化MinioClient。 3. 处理上传限制:调整Spring Boot配置(如果适用)。 4. 执行上传:调用putObject方法上传压缩后的图片。 需要注意的细节: - 图片压缩时的参数设置,如质量、尺寸调整。 - MinIO桶是否存在,是否需要检查或自动创建。 - 异常处理,比如连接失败、上传中断等。 - 内容类型的正确设置,例如image/jpeg或image/png。 可能的问题点: - 用户是否已经压缩图片,还是需要在代码中进行压缩?需要明确。 - 是否需要对图片进行格式转换? - MinIO服务器的网络访问是否通畅,权限是否正确。 现在根据这些思考,组织回答步骤,包含代码示例,并引用之前的参考内容。同时生成相关问题。</think>在Java中将压缩后的图像文件上传至MinIO对象存储服务,需要结合图像压缩和MinIO客户端操作。以下是具体实现步骤: --- ### **1. 图像压缩实现** 使用`ImageIO`和`BufferedImage`调整图像质量,需指定压缩参数: ```java import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.File; public class ImageCompressor { public static void compressImage(String inputPath, String outputPath, float quality) { try { BufferedImage image = ImageIO.read(new File(inputPath)); // 设置压缩参数 ImageWriter writer = ImageIO.getImageWritersByFormatName("jpg").next(); ImageWriteParam param = writer.getDefaultWriteParam(); param.setCompressionMode(ImageWriteParam.MODE_EXPLICIT); param.setCompressionQuality(quality); // 0.0~1.0,值越小压缩率越高 // 输出压缩后的图像 try (FileOutputStream fos = new FileOutputStream(outputPath)) { writer.setOutput(ImageIO.createImageOutputStream(fos)); writer.write(null, new IIOImage(image, null, null), param); } } catch (Exception e) { e.printStackTrace(); } } } ``` --- ### **2. MinIO客户端配置** 引入依赖并初始化客户端: ```xml <!-- Maven依赖 --> <dependency> <groupId>io.minio</groupId> <artifactId>minio</artifactId> <version>8.5.6</version> </dependency> ``` ```java import io.minio.MinioClient; public class MinioUploader { private static final String ENDPOINT = "https://play.min.io"; private static final String ACCESS_KEY = "minioadmin"; private static final String SECRET_KEY = "minioadmin"; public static MinioClient initMinioClient() { return MinioClient.builder() .endpoint(ENDPOINT) .credentials(ACCESS_KEY, SECRET_KEY) .build(); } } ``` --- ### **3. 文件上传大小限制配置(Spring Boot)** 若通过HTTP接口上传,需在`application.yml`中设置: ```yaml spring: servlet: multipart: max-file-size: 10MB # 单个文件最大限制[^2] max-request-size: 20MB # 请求整体最大限制 ``` --- ### **4. 上传压缩文件至MinIO** 调用`putObject`方法上传: ```java import io.minio.PutObjectArgs; public class UploadService { public static void uploadToMinio(String bucketName, String objectName, String filePath) { try { MinioClient minioClient = MinioUploader.initMinioClient(); // 检查存储桶是否存在,不存在则创建 boolean found = minioClient.bucketExists(bucketName); if (!found) { minioClient.makeBucket(bucketName); } // 上传文件 minioClient.putObject( PutObjectArgs.builder() .bucket(bucketName) .object(objectName) .filename(filePath) .contentType("image/jpeg") // 根据实际类型调整 .build() ); } catch (Exception e) { e.printStackTrace(); } } } ``` --- ### **完整调用示例** ```java public class Main { public static void main(String[] args) { // 1. 压缩图片 ImageCompressor.compressImage("original.jpg", "compressed.jpg", 0.5f); // 2. 上传至MinIO UploadService.uploadToMinio("images", "2023/compressed.jpg", "compressed.jpg"); } } ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值