SpringBoot整合MinIO上传下载文件

  1. 编写minio的pom.xml 依赖
		<dependency>
            <groupId>io.miniogroupId>
            <artifactId>minioartifactId>
            <version>8.0.3version>
        dependency>
  1. 编写minio配置文件application.yml
minio:
    endpoint: http://x.xxx.xxx.18:9000
    bucket: mall4cloud
    accessKey: admin
    secretKey: admin123456
  1. 编写minio服务接口
package cn.sh.ideal.service;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

import cn.sh.ideal.result.ServerResponseEntity;
import io.minio.errors.*;
import org.springframework.web.multipart.MultipartFile;

/**
 * @author Steven
 * @version 1.0
 * @date 2023/1/16 16:54
 * @description
 */
public interface MinIoService {

    ServerResponseEntity<String> upload(MultipartFile multipart) throws IOException, ServerException, InsufficientDataException, InternalException, InvalidResponseException, InvalidKeyException, NoSuchAlgorithmException, XmlParserException, ErrorResponseException;

    ServerResponseEntity<Boolean> delete(String path);

    ServerResponseEntity<String> getPresignedObjectUrl(String path);

    ServerResponseEntity<String> download(String path);

    ServerResponseEntity download(String path, HttpServletRequest request , HttpServletResponse response);
}
  1. 编写minio实现类
package cn.sh.ideal.service.impl;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.concurrent.TimeUnit;

import cn.hutool.core.util.StrUtil;
import cn.sh.ideal.config.MinIOConfigProperties;
import cn.sh.ideal.result.ServerResponseEntity;
import cn.sh.ideal.service.MinIoService;
import io.minio.*;
import io.minio.errors.*;
import io.minio.http.Method;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

/**
 * @author Steven
 * @version 1.0
 * @date 2023/1/16 16:48
 * @description
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class MinIOImpl implements MinIoService {

    private final MinioClient minClient;
    private final MinIOConfigProperties configProperties;

    @Override
    public ServerResponseEntity<String> upload(MultipartFile multipart) throws IOException, ServerException, InsufficientDataException, InternalException, InvalidResponseException, InvalidKeyException, NoSuchAlgorithmException, XmlParserException, ErrorResponseException {
       String path= StrUtil.uuid();
        // 校验桶
        boolean found = minClient.bucketExists(BucketExistsArgs.builder().bucket(configProperties.getBucket()).build());
        if (!found) {
            // 创建桶
            minClient.makeBucket(MakeBucketArgs.builder().bucket(configProperties.getBucket()).build());
        } else {
            System.out.println("桶名="+configProperties.getBucket()+" 已存在");
        }
       minClient.putObject(
               PutObjectArgs.builder()
                       .bucket(configProperties.getBucket())
                       .object(path)
                       .contentType(multipart.getContentType())
                       .stream(multipart.getInputStream(),multipart.getSize(),-1)
                       .build()
       );
        String filePath = new StringBuffer(configProperties.getEndpoint())
                .append("/")
                .append(configProperties.getBucket())
                .append("/")
                .append(path)
                .toString();
        return ServerResponseEntity.success(filePath);
    }

    @SneakyThrows
    @Override
    public ServerResponseEntity<Boolean> delete(String path) {
        minClient.removeObject(RemoveObjectArgs
                .builder()
                .bucket(configProperties.getBucket())
                .object(path)
                .build()
        );
        return null;
    }

    /**
     * 获得上传URL
     * @param path
     * @return
     */
    @SneakyThrows
    @Override
    public ServerResponseEntity<String> getPresignedObjectUrl(String path){
        String objectUrl = minClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs
                .builder()
                .bucket(configProperties.getBucket())
                .object(path)
                .expiry(10, TimeUnit.MINUTES)
                .method(Method.GET).build());
        return ServerResponseEntity.success(objectUrl);
    }

    @SneakyThrows
    @Override
    public ServerResponseEntity<String> download(String path){
        minClient.downloadObject(DownloadObjectArgs
                .builder()
                .bucket(configProperties.getBucket())
                .object(path)
                .filename("C:/eladmin/avatar/a.jpg")
                .build()
        );

        return ServerResponseEntity.success();
    }

    @SneakyThrows
    @Override
    public ServerResponseEntity download(String path, HttpServletRequest request, HttpServletResponse response){
        try {
            InputStream inputStream = minClient.getObject(GetObjectArgs
                    .builder()
                    .bucket(configProperties.getBucket())
                    .object(path)
                    .build());
            response.setCharacterEncoding(request.getCharacterEncoding());
            response.setContentType("application/octet-stream");
            response.setHeader("Content-Disposition", "attachment; filename=" + "a.jpg");
            IOUtils.copy(inputStream, response.getOutputStream());
            response.flushBuffer();
        }finally {

        }

        return ServerResponseEntity.success();
    }
}

  1. 编写minio控制类
package cn.sh.ideal.controller;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import cn.sh.ideal.result.ServerResponseEntity;
import cn.sh.ideal.service.MinIoService;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

/**
 * @author Steven
 * @version 1.0
 * @date 2023/1/16 16:45
 * @description
 */
@Slf4j
@RequiredArgsConstructor
@RestController
@RequestMapping("/minIO")
public class MinIOController {

    private final MinIoService minIoService;

    @SneakyThrows
    @PostMapping("/upload")
    public ServerResponseEntity<String> uploadFile(MultipartFile multipart){
        // 上传
        return minIoService.upload(multipart);
    }

    @GetMapping("/delete/{path}")
    public ServerResponseEntity delete(@PathVariable("path") String path){
        minIoService.delete(path);
        return ServerResponseEntity.success();
    }

    @GetMapping("/getUrl/{path}")
    public ServerResponseEntity getUrl(@PathVariable("path") String path){
        return minIoService.getPresignedObjectUrl(path);
    }

    @GetMapping("/download/{path}")
    public ServerResponseEntity download(@PathVariable("path") String path){
        return minIoService.download(path);
    }

    @PostMapping("/downloadHttp/{path}")
    public ServerResponseEntity download(@PathVariable("path") String path, HttpServletRequest request, HttpServletResponse response){
        return minIoService.download(path,request,response);
    }

}

  1. 编写结果集
package cn.sh.ideal.result;

/**
 * @author FrozenWatermelon
 * @date 2020/7/9
 */
public enum ResponseEnum {

	/**
	 * ok
	 */
	OK("00000", "ok"),

	/**
	 * 用于直接显示提示用户的错误,内容由输入内容决定
	 */
	SHOW_FAIL("A00001", ""),

	/**
	 * 方法参数没有校验,内容由输入内容决定
	 */
	METHOD_ARGUMENT_NOT_VALID("A00002", ""),

	/**
	 * 无法读取获取请求参数
	 */
	HTTP_MESSAGE_NOT_READABLE("A00003", "请求参数格式有误"),

	/**
	 * 未授权
	 */
	UNAUTHORIZED("A00004", "Unauthorized"),

	/**
	 * 服务器出了点小差
	 */
	EXCEPTION("A00005", "服务器出了点小差"),

	/**
	 * 数据异常
	 */
	DATA_ERROR("A00007", "数据异常,请刷新后重新操作"),

	/**
	 * 一些需要登录的接口,而实际上因为前端无法知道token是否已过期,导致token已失效时,
	 * 应该返回一个状态码,告诉前端token已经失效了,及时清理
	 */
	CLEAN_TOKEN("A00008", "clean token"),

	/**
	 * 刷新token已过期
	 */
	REFRESH_TOKEN_EXIST("A00009", "refresh token exist"),

	/**
	 * 数据不完整
	 */
	DATA_INCOMPLETE("A00010", "数据不完整"),

	/**
	 * 01开头代表商品
	 */
	SPU_NOT_EXIST("A01000", "spu not exist"),

	/**
	 * 02开头代表购物车
	 */
	SHOP_CART_NOT_EXIST("A02000", "shop cart not exist"),

	/**
	 * 03开头代表订单
	 */
	ORDER_NOT_EXIST("A03000", "order not exist"),

	/**
	 * 请勿重复提交订单,
	 * 1.当前端遇到该异常时,说明前端防多次点击没做好
	 * 2.提示用户 订单已发生改变,请勿重复下单
	 */
	REPEAT_ORDER("A03002", "please don't repeat order"),

	/**
	 * 订单已过期,当前端看到该状态码的时候,提示订单信息已过期,请重新确认后提交,此时用户点击确定,前端刷新页面。
	 */
	ORDER_EXPIRED("A03003", "order expired"),

	/**
	 * 订单已支付,无法取消订单
	 */
	ORDER_PAYED("A03007", "order payed"),

	/**
	 * 订单未发货,无法确认收货
	 */
	ORDER_NO_DELIVERY("A03008", "order no delivery"),

	/**
	 * 库存不足,body会具体返回那个skuid的库存不足
	 */
	NOT_STOCK("A03010", "not stock"),

	/**
	 * 订单未完成或未关闭,无法删除订单
	 */
	ORDER_NOT_FINISH_OR_CLOSE("A03011", "order not finish or close"),

	/**
	 * 订单未支付
	 */
	ORDER_NOT_PAYED("A03012", "order not payed"),

	/**
	 * 订单已失败
	 */
	ORDER_HAS_FAILED("A03013", "order has failed"),

	/**
	 * 没有查询权限
	 */
	REFUND_NOT_PERMISSION("A03024", "refund not permission"),

	/**
	 * 撤销失败 当前状态不允许此操作
	 */
	REFUND_STATUS_CHECK("A03034", "refund status check"),

	/**
	 * 04 开头代表注册登录之类的异常状态
	 * 社交账号未绑定,当前端看到该异常时,应该在合适的时间(比如在购买的时候跳)根据社交账号的类型,跳转到绑定系统账号的页面
	 */
	SOCIAL_ACCOUNT_NOT_BIND("A04001", "social account not bind"),

	/**
	 * 有些时候第三方系统授权之后,会有个临时的key,比如小程序的session_key
	 * 这个异常代表session_key过期,前端遇到这个问题的时候,应该再次调用社交登录的接口,刷新session_key
	 */
	BIZ_TEMP_SESSION_KEY_EXPIRE("A04002", "biz temp session key expire"),

	/**
	 * 账号未注册,前端看到这个状态码,弹出选择框,提示用户账号未注册,是否进入注册页面,用户选择是,进入注册页面
	 */
	ACCOUNT_NOT_REGISTER("A04003", "account not register");
    private final String code;

	private final String msg;

	public String value() {
		return code;
	}

	public String getMsg() {
		return msg;
	}

	ResponseEnum(String code, String msg) {
		this.code = code;
		this.msg = msg;
	}

	@Override
	public String toString() {
		return "ResponseEnum{" + "code='" + code + '\'' + ", msg='" + msg + '\'' + "} " + super.toString();
	}

}

package cn.sh.ideal.result;

import java.io.Serializable;
import java.util.Objects;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 统一的返回数据
 *
 * @author FrozenWatermelon
 * @date 2020/7/3
 */
public class ServerResponseEntity<T> implements Serializable {

	private static final Logger log = LoggerFactory.getLogger(ServerResponseEntity.class);

	/**
	 * 状态码
	 */
	private String code;

	/**
	 * 信息
	 */
	private String msg;

	/**
	 * 数据
	 */
	private T data;

	public String getCode() {
		return code;
	}

	public void setCode(String code) {
		this.code = code;
	}

	public String getMsg() {
		return msg;
	}

	public void setMsg(String msg) {
		this.msg = msg;
	}

	public T getData() {
		return data;
	}

	public void setData(T data) {
		this.data = data;
	}

	public boolean isSuccess() {
		return Objects.equals(ResponseEnum.OK.value(), this.code);
	}

	@Override
	public String toString() {
		return "ServerResponseEntity{" + "code=" + code + ", msg='" + msg + '\'' + ", data=" + data + '}';
	}

	public static <T> ServerResponseEntity<T> success(T data) {
		ServerResponseEntity<T> serverResponseEntity = new ServerResponseEntity<>();
		serverResponseEntity.setData(data);
		serverResponseEntity.setCode(ResponseEnum.OK.value());
		return serverResponseEntity;
	}

	public static <T> ServerResponseEntity<T> success() {
		ServerResponseEntity<T> serverResponseEntity = new ServerResponseEntity<>();
		serverResponseEntity.setCode(ResponseEnum.OK.value());
		serverResponseEntity.setMsg(ResponseEnum.OK.getMsg());
		return serverResponseEntity;
	}

	/**
	 * 前端显示失败消息
	 * @param msg 失败消息
	 * @return
	 */
	public static <T> ServerResponseEntity<T> showFailMsg(String msg) {
		log.error(msg);
		ServerResponseEntity<T> serverResponseEntity = new ServerResponseEntity<>();
		serverResponseEntity.setMsg(msg);
		serverResponseEntity.setCode(ResponseEnum.SHOW_FAIL.value());
		return serverResponseEntity;
	}

	public static <T> ServerResponseEntity<T> fail(ResponseEnum responseEnum) {
		log.error(responseEnum.toString());
		ServerResponseEntity<T> serverResponseEntity = new ServerResponseEntity<>();
		serverResponseEntity.setMsg(responseEnum.getMsg());
		serverResponseEntity.setCode(responseEnum.value());
		return serverResponseEntity;
	}

	public static <T> ServerResponseEntity<T> fail(ResponseEnum responseEnum, T data) {
		log.error(responseEnum.toString());
		ServerResponseEntity<T> serverResponseEntity = new ServerResponseEntity<>();
		serverResponseEntity.setMsg(responseEnum.getMsg());
		serverResponseEntity.setCode(responseEnum.value());
		serverResponseEntity.setData(data);
		return serverResponseEntity;
	}

	public static <T> ServerResponseEntity<T> transform(ServerResponseEntity<?> oldServerResponseEntity) {
		ServerResponseEntity<T> serverResponseEntity = new ServerResponseEntity<>();
		serverResponseEntity.setMsg(oldServerResponseEntity.getMsg());
		serverResponseEntity.setCode(oldServerResponseEntity.getCode());
		log.error(serverResponseEntity.toString());
		return serverResponseEntity;
	}

}

你可能感兴趣的:(文件存储,Spring,Boot,spring,boot,minio文件存储)