如何在springboot项目中使用minio上传下载删除文件

引入maven依赖

<!--  minio   -->
<dependency>
    <groupId>io.minio</groupId>
    <artifactId>minio</artifactId>
    <version>8.2.2</version>
</dependency>

申请 bucket | access_key | secret_key

项目中配置相关参数

    minio:
        # access_key
        accessKey: xxxxxx
        # secret_key
        secretKey: xxxxxx
        # bucket
        bucketName: bucket1
        # 内网地址
        endpoint: http://127.0.0.1:9000
        # 外网地址
        website: https://xxx.xxx.cn:9000
        # 自定义文件大小限制 注:要与spring.servlet.multipart.max-file-size | max-request-size 区分开
        maxFileSize:
            img: 10
            video: 30

endpoint | website | maxFileSize 可根据项目需要增删,后面不再赘述。

Minio 配置信息


/**
 * Minio 配置信息
 *
 * @author ruoyi
 */
@Configuration
@ConfigurationProperties(prefix = "minio")
public class MinioConfig
{
    /**
     * 用户名
     */
    private String accessKey;

    /**
     * 密码
     */
    private String secretKey;

    /**
     * 存储桶名称
     */
    private String bucketName;

    /**
     * 服务地址
     */
    private String endpoint;

    /**
     * 公网
     */
    private String webSite;

    /**
     * 文件大小限制
     */
    private MediaMaxFileSize maxFileSize;

    public static class MediaMaxFileSize{
        private Long img;
        private Long video;

        public Long getImg() {
            return img;
        }

        public void setImg(Long img) {
            this.img = img;
        }

        public Long getVideo() {
            return video;
        }

        public void setVideo(Long video) {
            this.video = video;
        }
    }

    public String getWebSite() {
        return webSite;
    }

    public void setWebSite(String webSite) {
        this.webSite = webSite;
    }

    public MediaMaxFileSize getMaxFileSize() {
        return maxFileSize;
    }

    public void setMaxFileSize(MediaMaxFileSize maxFileSize) {
        this.maxFileSize = maxFileSize;
    }

    public String getAccessKey() {
        return accessKey;
    }

    public void setAccessKey(String accessKey) {
        this.accessKey = accessKey;
    }

    public String getSecretKey() {
        return secretKey;
    }

    public void setSecretKey(String secretKey) {
        this.secretKey = secretKey;
    }

    public String getBucketName() {
        return bucketName;
    }

    public void setBucketName(String bucketName) {
        this.bucketName = bucketName;
    }

    public String getEndpoint() {
        return endpoint;
    }

    public void setEndpoint(String endpoint) {
        this.endpoint = endpoint;
    }

    @Bean
    public MinioClient getMinioClient() {
        return MinioClient.builder().endpoint(endpoint).credentials(accessKey, secretKey).build();
    }
}


/**
 * 文件对象实体类
 */
public class MinioFile implements Serializable {

    // 文件服务器文件所属组
    private String bucketName;
    // 不带文件组的文件URL
    private String path;
    // 带文件组的文件URL
    private String fullPath;
    // 站点信息
    private String webSite;
    // 带站点的文件URL
    private String webUrl;
    // 原始文件名
    private String fileName;
    // 内网廉价而
    private String intranetWebSite;
    // 内网地址
    private String intranetWebUrl;

    // 其他参数
    private Map<String, Object> params = new HashMap<>();

    public String getFullPath() {
        return fullPath;
    }

    public void setFullPath(String fullPath) {
        this.fullPath = fullPath;
    }

    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }

    public String getWebSite() {
        return webSite;
    }

    public void setWebSite(String webSite) {
        this.webSite = webSite;
    }

    public String getWebUrl() {
        return webUrl;
    }

    public void setWebUrl(String webUrl) {
        this.webUrl = webUrl;
    }

    public String getFileName() {
        return fileName;
    }

    public void setFileName(String fileName) {
        this.fileName = fileName;
    }

    public String getIntranetWebUrl() {
        return intranetWebUrl;
    }

    public void setIntranetWebUrl(String intranetWebUrl) {
        this.intranetWebUrl = intranetWebUrl;
    }

    public String getIntranetWebSite() {
        return intranetWebSite;
    }

    public void setIntranetWebSite(String intranetWebSite) {
        this.intranetWebSite = intranetWebSite;
    }

    public String getBucketName() {
        return bucketName;
    }

    public void setBucketName(String bucketName) {
        this.bucketName = bucketName;
    }

    public Map<String, Object> getParams() {
        if (params == null) {
            params = new HashMap<>();
        }
        return params;
    }

    public void setParams(Map<String, Object> params) {
        this.params = params;
    }

    public Object getParam(String key) {
        if (params == null) {
            params = new HashMap<>();
            return null;
        }
        return params.get(key);
    }

    public void putParam(String key, Object value) {
        if (params == null) {
            params = new HashMap<>();
        }
        params.put(key, value);
    }

}

文件上传下载删除工具类封装

项目基于RuoYi开源框架搭建,因此此处工具类引入开源框架中一些内置工具类


import com.ruoyi.common.exception.file.InvalidExtensionException;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.file.FileUploadUtils;
import com.ruoyi.common.utils.file.MimeTypeUtils;
import com.ruoyi.common.utils.uuid.Seq;
import io.minio.GetPresignedObjectUrlArgs;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import io.minio.RemoveObjectArgs;
import io.minio.http.Method;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.io.InputStream;
import java.util.Date;

/**
 * Minio 文件存储工具类
 * 
 * @author ruoyi
 */
@Component
public class MinioUtil
{
    private static Logger log = LoggerFactory.getLogger(MinioUtil.class);
    /**
     * minio实例
     */
    private static MinioClient minioClient;

    /**
     * minio配置类
     */
    private static MinioConfig minioConfig;

    @Autowired
    public void setMinioUtil(MinioClient minioClient, MinioConfig minioConfig){
        MinioUtil.minioClient = minioClient;
        MinioUtil.minioConfig = minioConfig;
    }

    public MinioFile uploadFile(MultipartFile file, String fileType, String filePurpose) throws InvalidExtensionException, IOException {
        if("01".equals(fileType)){
            FileUploadUtils.assertAllowed(file, MimeTypeUtils.IMAGE_EXTENSION_10001, minioConfig.getMaxFileSize().getImg() * 1024 * 1024);
        } else if ("02".equals(fileType)) {
            FileUploadUtils.assertAllowed(file, MimeTypeUtils.VIDEO_EXTENSION_10002, minioConfig.getMaxFileSize().getVideo() * 1024 * 1024);
        }
        // 年月
        String yyyyMM = DateUtils.parseDateToStr("yyyyMM", new Date());
        // 文件名 moduleName/业务类型/文件类型/年月/Seq随机字符/文件后缀
        String fileName = StringUtils.format("{}/{}/{}/{}/{}.{}"
                ,"moduleName"
                , getFilePurpose(filePurpose)// 使用用途
                , getFileType(fileType)//文件类型
                , yyyyMM
                , Seq.getId()
                , FileUploadUtils.getExtension(file));
        return uploadFile(file, fileName);
    }

    private MinioFile uploadFile(MultipartFile file, String fileName) throws IOException {
        String webUrl = uploadFile(minioConfig.getBucketName(), fileName, file);
        MinioFile minioFile = new MinioFile();
        minioFile.setBucketName(minioConfig.getBucketName());
        minioFile.setPath(fileName);
        minioFile.setFullPath(StringUtils.format("{}/{}",minioConfig.getBucketName(),fileName));
        minioFile.setWebSite(minioConfig.getWebSite());
        minioFile.setWebUrl(webUrl.replace(minioConfig.getEndpoint(),minioConfig.getWebSite()));
        minioFile.setFileName(file.getOriginalFilename());
        minioFile.setIntranetWebSite(minioConfig.getEndpoint());
        minioFile.setIntranetWebUrl(webUrl);
        return minioFile;
    }

    /**
     * 上传文件
     * 
     * @param bucketName 桶名称
     * @param fileName
     * @throws IOException
     */
    private String uploadFile(String bucketName, String fileName, MultipartFile multipartFile) throws IOException
    {
        String url = "";
        try (InputStream inputStream = multipartFile.getInputStream())
        {
            minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(fileName).stream(inputStream, multipartFile.getSize(), -1).contentType(multipartFile.getContentType()).build());
            url = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().bucket(bucketName).object(fileName).method(Method.GET).build());
            url = url.substring(0, url.indexOf('?'));
            return ServletUtils.urlDecode(url);
        }
        catch (Exception e)
        {
            throw new IOException(e.getMessage(), e);
        }
    }

    /**
     * 删除文件
     * @param fileName
     */
    public void removeFile(String fileName){
        try
        {
            minioClient.removeObject(RemoveObjectArgs.builder().bucket(minioConfig.getBucketName()).object(fileName).build());
        }
        catch (Exception e)
        {
            e.printStackTrace();
            log.error("MinioUtil-uploadMinio-error", e);
        }
    }

    /**
     * 文件类型 可自定义
     * @param fileType
     * @return
     */
    private String getFileType(String fileType){
        String fileTypeName = null;
        switch (fileType){
            case "01":
                fileTypeName = "image";
                break;
            case "02":
                fileTypeName = "video";
                break;
            default:
                fileTypeName = "undefined";
        }
        return fileTypeName;
    }

    /**
     * 获取文件使用用途 可自定义
     * @param filePurpose
     * @return
     */
    private String getFilePurpose(String filePurpose){
        String filePurposeType = null;
        switch (filePurpose){
            case "01":
                filePurposeType = "banner";
                break;
            default:
                filePurposeType = "undefined";
        }
        return filePurposeType;
    }

}

MimeTypeUtils.IMAGE_EXTENSION_10001 和 MimeTypeUtils.VIDEO_EXTENSION_10002为在原框架工具类上新增自定义文件后缀
另根据业务需要,对框架FileUploadUtils中的assertAllowed进行方法重载

/**
     * 文件大小校验
     *
     * @param file 上传的文件
     * @return
     * @throws FileSizeLimitExceededException 如果超出最大大小
     * @throws InvalidExtensionException
     */
    public static final void assertAllowed(MultipartFile file, String[] allowedExtension)
            throws FileSizeLimitExceededException, InvalidExtensionException
    {
        assertAllowed(file, allowedExtension, DEFAULT_MAX_SIZE);
    }

    /**
     * 文件大小校验
     *
     * @param file 上传的文件
     * @param maxSize 最大限制
     * @return
     * @throws FileSizeLimitExceededException 如果超出最大大小
     * @throws InvalidExtensionException
     */
    public static final void assertAllowed(MultipartFile file, String[] allowedExtension, long maxSize)
            throws FileSizeLimitExceededException, InvalidExtensionException
    {
        long size = file.getSize();
        if (size > maxSize)
        {
            throw new FileSizeLimitExceededException(maxSize / 1024 / 1024);
        }

        String fileName = file.getOriginalFilename();
        String extension = getExtension(file);
        if (allowedExtension != null && !isAllowedExtension(extension, allowedExtension))
        {
            if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION)
            {
                throw new InvalidExtensionException.InvalidImageExtensionException(allowedExtension, extension,
                        fileName);
            }
            else if (allowedExtension == MimeTypeUtils.FLASH_EXTENSION)
            {
                throw new InvalidExtensionException.InvalidFlashExtensionException(allowedExtension, extension,
                        fileName);
            }
            else if (allowedExtension == MimeTypeUtils.MEDIA_EXTENSION)
            {
                throw new InvalidExtensionException.InvalidMediaExtensionException(allowedExtension, extension,
                        fileName);
            }
            else if (allowedExtension == MimeTypeUtils.VIDEO_EXTENSION)
            {
                throw new InvalidExtensionException.InvalidVideoExtensionException(allowedExtension, extension,
                        fileName);
            }
            else if (allowedExtension == MimeTypeUtils.IMAGE_EXTENSION_10001)
            {
                throw new InvalidExtensionException.InvalidImageExtensionException(allowedExtension, extension,
                        fileName);
            }
            else if (allowedExtension == MimeTypeUtils.VIDEO_EXTENSION_10002)
            {
                throw new InvalidExtensionException.InvalidVideoExtensionException(allowedExtension, extension,
                        fileName);
            }
            else
            {
                throw new InvalidExtensionException(allowedExtension, extension, fileName);
            }
        }
    }
  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值