SpringBoot使用Maven整合minio实现静态资源和对象的存储;解决与okhttp依赖冲突问题

2023-05-16

1.minio部署

推荐使用DockerCompose部署

可参考下面的地址:
Minio官网(中文):http://www.minio.org.cn/
DockerHub地址:https://hub.docker.com/r/minio/minio
DockerCompose部署minio:Docker使用docker compose单机部署对象存储系统minio (2022新版本)

2.添加maven依赖

在这里插入图片描述

依赖:

		<dependency>
			<groupId>io.minio</groupId>
			<artifactId>minio</artifactId>
			<version>8.0.3</version>
		</dependency>

注意:这个依赖很容易和HTTP请求的依赖产生依赖冲突的问题
可以通过添加dependencyManagement来解决这类问题,还有依赖的顺序也要注意
这里以okhttps来举例

		<!-- minIO对象存储-->
		<dependency>
			<groupId>io.minio</groupId>
			<artifactId>minio</artifactId>
			<version>8.0.3</version>
		</dependency>

		<!-- Http请求工具 -->
		<dependency>
		     <groupId>com.ejlchina</groupId>
		     <artifactId>okhttps</artifactId>
			<version>3.5.2</version>
		</dependency>
	<dependencyManagement>
		<dependencies>
			<dependency>
				<groupId>com.squareup.okhttp3</groupId>
				<artifactId>okhttp</artifactId>
				<version>3.14.4</version>
			</dependency>
		</dependencies>
	</dependencyManagement>

3.编写配置文件

因为minio的配置是需要我们自己来读取的,所以名称无所谓,但还是应该尽量规范一些
此处,我们以yml格式为例

minio:
    endpoint: http://192.168.200.128:9000 #地址
    accessKey: admin  	#用户名
    secretKey: admin123 #密码
    bucketName: application #桶
    downloadURL: http://192.168.0.119:9000/minio/download/ #下载地址

4.编写minio的配置类

import io.minio.MinioClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Component;

@Configuration
@Component
public class MinIOClientConfig {
    @Value("${minio.accessKey}")
    private String accessKey;
    @Value("${minio.endpoint}")
    private String endpoint;
    @Value("${minio.secretKey}")
    private String secretKey;

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

}

这一步完成后,可以启动项目测试一下,如果没有报错,就说明minio连接成功了

5.通过minio存储静态资源

先编写一个返回类,已经有的话,根据情况改返回的结构就行
用到的依赖有lombokswagger,可以根据需求调整

状态码:

public interface ResultCode {
    Integer SUCCESS = 200;
    Integer ERROR = 500;
}

返回类:

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;

import java.util.HashMap;
import java.util.Map;

@Data
public class R {

    @ApiModelProperty(value = "是否成功")
    private Boolean success;

    @ApiModelProperty(value = "返回码")
    private Integer code;

    @ApiModelProperty(value = "返回消息")
    private String message;

    @ApiModelProperty(value = "返回数据")
    private Map<String, Object> data = new HashMap<String, Object>();

    private R(){}

    public static R ok(){
        R r = new R();
        r.setSuccess(true);
        r.setCode(ResultCode.SUCCESS);
        r.setMessage("成功");
        return r;
    }

    public static R error(){
        R r = new R();
        r.setSuccess(false);
        r.setCode(ResultCode.ERROR);
        r.setMessage("失败");
        return r;
    }

    public R success(Boolean success){
        this.setSuccess(success);
        return this;
    }

    public R message(String message){
        this.setMessage(message);
        return this;
    }

    public R code(Integer code){
        this.setCode(code);
        return this;
    }

    public R data(String key, Object value){
        this.data.put(key, value);
        return this;
    }

    public R data(Map<String, Object> map){
        this.setData(map);
        return this;
    }
}

编写minio的Controller类

import io.minio.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.FastByteArrayOutputStream;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.util.Objects;
import java.util.UUID;

@CrossOrigin
@RestController
@RequestMapping("minio")
public class MinIOController {
    @Resource
    private MinioClient minioClient;

    /*
    * 存哪个桶
    * */
    @Value("${minio.bucketName}")
    private String bucketName;

	//下载文件的路径
    @Value("${minio.downloadURL}")
    private String downloadURL;

    /*
    * 获取文件名称
    * */
    public String getFileName(String name){
        String[] split = name.split("\\.");
        //随机文件名称
        return UUID.randomUUID() + "." + split[split.length-1];
    }

    /*
    * 文件上传
    * */
    @PostMapping("/upload")
    public R upload(MultipartFile file){
        try {

            String fileName = getFileName(Objects.requireNonNull(file.getOriginalFilename()));
            PutObjectArgs objectArgs = PutObjectArgs.builder().object(fileName)
                    .bucket(bucketName)
                    .contentType(file.getContentType())
                    .stream(file.getInputStream(),file.getSize(),-1).build();

            minioClient.putObject(objectArgs);
            return R.ok().message(downloadURL + fileName);
        } catch (Exception e) {
            System.err.println(e.getMessage());
            return R.error().message(e.getMessage());
        }
    }

    /**
     * 下载文件
     */
    @GetMapping("/download/{filename}")
    public void download(@PathVariable String filename, HttpServletResponse res){

        GetObjectArgs objectArgs = GetObjectArgs.builder().bucket(bucketName)
                .object(filename).build();

        try (GetObjectResponse response = minioClient.getObject(objectArgs)){
            byte[] buf = new byte[1024];

            int len;

            try (FastByteArrayOutputStream os = new FastByteArrayOutputStream()){

                while ((len=response.read(buf))!=-1){

                    os.write(buf,0,len);

                }
                os.flush();

                byte[] bytes = os.toByteArray();

                res.setCharacterEncoding("utf-8");
//                res.setContentType("application/force-download");// 设置强制下载不打开
                res.addHeader("Content-Disposition", "attachment;fileName=" + filename);
                try ( ServletOutputStream stream = res.getOutputStream()){
                    stream.write(bytes);
                    stream.flush();
                }
            }

        } catch (Exception e) {
            System.err.println(e.getMessage());
        }
    }

    /**
     * 删除文件
     *
     * @param fileName 文件路径
     * @return
     */
    @DeleteMapping("/deleteFile/{fileName}")
    public R deleteFile(@PathVariable("fileName") String fileName) {
        try {
            minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(fileName).build());
        } catch (Exception e){
            System.err.println(e.getMessage());
            return R.error();
        }
        return R.ok();
    }

}

打开swagger测试一下,也可以用其他工具

在这里插入图片描述
接口会返回下载浏览的路径
在这里插入图片描述
成功

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SpringBoot使用Maven整合minio实现静态资源和对象的存储;解决与okhttp依赖冲突问题 的相关文章

  • 实现AntDesign组件的按需导入

    昨天我们演示了如何为React项目启用AntDesign组件 xff0c 现在回顾一下 xff0c 引入方法为 xff1a span class token keyword import span span class token punc
  • 三分钟搭建React + Electron开发环境

    三分钟搭建React 43 Electron开发环境 背景创建React项目添加Electron包相关配置项目根目录下新建main js配置package json启动electron 启动效果 背景 先前的博客中介绍过怎么通过Webpac
  • 快速打包React+Electron项目

    背景 上一篇博客介绍了如何快速搭建React 43 Electron的开发环境 xff0c 简单应用开发完毕后需要打包成应用程序 xff0c 比如你需要把你开发的App发给其他人使用 下面基于上一篇博客内容进一步介绍如何打包 xff1a 打
  • 在Dart中使用FFI调用Rust函数

    什么是FFI 外部函数接口 FFI 是一种机制 xff0c 通过该机制 xff0c 以一种编程语言编写的程序可以调用以另一种编程语言编写的服务 当你需要额外的速度 x1f680 或需要使用其他语言的库时 xff0c 应用FFI会很方便 为什
  • Qt6播放音频文件

    Qt6中已经没有QSound类 xff0c 播放音频需要使用QSoundEffect类 首先在 pro文件中添加multimedia模块 使用方法 xff1a include span class token operator lt spa
  • 牛客NC61 两数之和

    题目描述 给出一个整型数组 numbers 和一个目标值 target xff0c 请在数组中找出两个加起来等于目标值的数的下标 xff0c 返回的下标按升序排列 xff08 注 xff1a 返回的数组下标从1开始算起 xff0c 保证ta
  • 牛客HJ20 密码验证合格程序

    描述 密码要求 1 长度超过8位 2 包括大小写字母 数字 其它符号 以上四种至少三种 3 不能有长度大于2的包含公共元素的子串重复 xff08 注 xff1a 其他符号不含空格或换行 xff09 输入描述 xff1a 一组字符串 输出描述
  • React useEffect vs useLayoutEffect

    两者的区别 两者的函数签名是一样的 xff0c 即用法一样 两者的区别在于执行时机不同 useEffect是在DOM的变化渲染到屏幕后异步执行的useLayoutEffect是在DOM变化后渲染前同步执行的 因此从执行时机上看 xff0c
  • 单片机产生二维8*8随机数

    代码可运行 span class token keyword void span span class token function Random span span class token punctuation span span cl
  • React useCallback 函数使用说明

    React 中useCallback的作用 xff1a 函数相等性检查 useCallback 的函数原型 xff1a useCallback callbackFun deps 如果deps给出的依赖值不变 xff0c 则useCallba
  • thinkpad t400在fedora 17上风扇转速调整

    作者 xff1a bigluo 转自 xff1a http blog chinaunix net uid 796091 id 3282943 html 在t400上安装了fedora 17 在编译代码的时候经常碰到下面的严重警告 xff0c
  • Python 把秒数转换为xx:xx:xx的时间格式

    题目要求是将给出的秒数转化为xx xx xx的格式 xff0c 最大秒数默认不超过359999 xff0c 即99 59 59 解题思路是利用除法的取整和取余运算 xff0c 从最高位计算到最低位 xff0c 只需根据题设注意时分秒各自的进
  • warning : 无法找到 v142 的生成工具。安装 v142 可使用 v142 生成工具进行生成。

    我使用的是vs2017 xff0c 同伴的是vs2019 xff0c 他发送了他写的项目给我 xff0c 因为使用的vs版本不同 工具集不同 xff0c 导致项目在我的电脑上编译会有如下报错 xff1a warning 无法找到 v142
  • 用栈判断是否是回文

    用栈判断是否是回文 栈 xff1a 仅在表尾进行插入和删除操作的线性表 先进后出 用例 xff1a 1 上海自来水来自海上 2 1234321 3 123321 4 112233 5 123332 思路 xff1a 直接入栈一半的元素 xf
  • VirtualBox安装Arch Linux

    xff08 转载自http www aichengxu com view 34792 xff0c 略有改动 xff09 所有步骤用于指导新手完成archlinux在虚拟机上的安装 xff0c 安装选择未必最优 xff0c 但尽力做到减少新手
  • KEIL UV5 一模一样的程序,编译突然就有问题了

    原来是系统时间调到2000年 xff0c 没有调回来 把时间调回来就可以了
  • 简单选择排序——C语言实现

    选择排序思想 xff1a 若按照递增顺序对顺序表进行排列 xff0c 在n个元素的顺序表中 xff0c 从第i xff08 i 61 1 xff09 个元素开始遍历到第n 1个元素 xff0c 在遍历过程中都将第i个元素依次与第i 43 1
  • php7+操作 MongoDB4.0

    php7 43 操作 MongoDB4 0 一 连接MongoDB服务 mongo 61 new MongoDB Driver Manager 34 mongodb localhost 27017 34 二 添加数据 实例化一个添加类 bu
  • centos图形界面的开启和关闭

    centos图形界面的开启和关闭 一般来说centos主要用于服务器端 xff0c 所以很少开启图形化界面 xff0c 但是有时候为了工作方便也会偶尔开启图形界面 xff0c 下面就让简单谈谈如何开启图形化界面 xff0c 当然简化安装是没
  • 远程连接——NoMachine

    参考文章 安装并使用NoMachine关于nomachine无法连接NX的问题 小贴士 在使用NoMachine的时候 xff0c 需要主机和从机都需要开启NoMachine软件长时间没连接NoMachine xff0c 可能会出现NoMa

随机推荐