小工具知识网

当前位置: 首页 > 行业知识 > springboot整合minio(实现文件的上传和下载超详细入门)

行业知识

springboot整合minio(实现文件的上传和下载超详细入门)

2026-11-08 15:44:43 来源:互联网转载

一、Minio介绍:

目前可用于文件存储的网络服务选择也有不少,比如阿里云OSS、七牛云、腾讯云等等,可是收费都有点小贵。为了省钱,很多公司使用MinIO做为文件服务器。

官网:https://www.minio.org.cn/

 MinIO是一个开源的分布式对象存储服务器,支持S3协议并且可以在多节点上实现数据的高可用和容错。它采用Go语言开发,拥有轻量级、高性能、易部署等特点,并且可以自由选择底层存储介质。它基于Apache License 开源协议,兼容Amazon S3云存储接口。适合存储非结构化数据,如图片,音频,视频,日志等。

二、Minio的下载:

有Windows和Linux两种方式,不过我们一般把服务器下载到Linux中。使用docker来部署,能够很方便的管理(默认你的Linux中已经下载好docker了)。

//拉取镜像

docker pull quay.io/minio/minio

// 创建数据存储目录

mkdir -p ~/minio/data

// 创建minio

docker run \

   -p 9001:9000 \

   -p 9090:9090 \

   --name minio \

   -v ~/minio/data:/data \

   -e "MINIO_ROOT_USER=admin" \

   -e "MINIO_ROOT_PASSWORD=admin123456" \

   -d \

   quay.io/minio/minio server /data --console-address ":9090"

在这里解释一下这个命令:

docker pull 拉取Minio的镜像,我没有指定版本,所以默认下载最新版本。

mkdir -p ~/minio/data:创建一个文件夹来存储我们上传到Minio中的文件。

实际上,我们上传到Minio中的文件都存储到了这个文件夹中。也就是说我们上传到Minio中的文件其实都保存在你的Linux服务器中。

docker run :创建容器并运行。解释一下重要的几个参数。

9001:Minio的服务端端口

9090:Minio的客户端端口

-v ~/minio/data:/data :数据卷挂载我们之前创建的文件夹,使之成为Minio的存储容器

-e "MINIO_ROOT_USER=admin" :用户名为admin

-e "MINIO_ROOT_PASSWORD=admin123456" :密码为admin123456

将容器运行起来:

现在登录我们的客户端,并输入用户名和密码:

http://Ip地址:9090

我们还要了解一下“桶”在Minio中的概念:

"桶"(Bucket)是用来组织和管理存储的对象(文件或文件夹)的基本单位。你可以把它想象成一个容器,用来存放你的对象。

以下是关于桶的一些重要概念:

  1. 命名:每个桶都有一个全局唯一的名称。这意味着在同一个MinIO服务中,不能有两个名称相同的桶。

  2. 隔离:桶之间是完全隔离的。一个桶中的对象不能直接访问另一个桶中的对象。

  3. 访问控制:每个桶都可以有自己的访问控制策略。例如,你可以设置一个桶为公开,任何人都可以读取它的内容;也可以设置一个桶为私有,只有特定的用户可以访问它的内容。

  4. 无限制的对象存储:每个桶内可以存储无限数量的对象,只要你的存储空间足够。

  5. 元数据:每个桶都可以有一些元数据,如创建时间、修改时间等。

可以选择在客户端创建桶,也可以使用Java代码来创建,我这里就使用Java代码创建桶了。

三、使用spring boot整合Minio,完成文件的上传、下载和删除。

版本:spring boot3、jdk17、Minio的版本为:RELEASE.2023-11-01T18-37-25Z

本次使用knife4j进行测试;

创建一个空的spring boot项目,并引入如下依赖:

            org.springframework.boot        spring-boot-starter-web                com.github.xiaoymin        knife4j-openapi3-jakarta-spring-boot-starter        4.3.0                io.minio        minio        8.5.2        org.projectlombok    lombok

在yml配置文件中引入如下配置:

minio:  url: http://192.168.231.110:9001  username: admin  password: admin123456  bucketName: testspring:  servlet:    multipart:      max-file-size:  10MB   # 单个文件上传的最大上限      max-request-size:  100MB  # 整个请求体的最大上限

minio:我们自定义的属性

url:你的服务端地址

username:用户名

password:密码

bucketName:test(桶的名称,我们现在没有创建,一会用Java代码实现)

max-file-size:一定要配置这个属性,不然springboot默认的单个文件上传的最大上限为1MB,超过这个上限,就会报错。

1、创建一个实体类来继承yml文件中minio的连接信息;

@ConfigurationProperties(prefix = "minio")@Component@Datapublic class MinioPojo {private String url;private String username;private String password;private String bucketName;}

2、自定义bean,将MinioClient初始化;

@Configurationpublic class MinioConfig {    @Autowired    private MinioPojo minioPojo;@Bean    public MinioClient minioClient(){    return MinioClient.builder()            .endpoint(minioPojo.getUrl())  //传入url地址                //传入用户名和密码            .credentials(minioPojo.getUsername(), minioPojo.getPassword())            .build();  //完成MinioClient的初始化    }}

3、新创建一个MinioService类,用来进行文件的操作,并注册为bean。将来在这里进行具体代码的编写。

@Componentpublic class MinioService {    @Autowired    private MinioClient minioClient;    @Autowired    private MinioPojo minioPojo;

}

4、新建一个Controller,用来进行文件的上传。

@RestController@RequestMapping("/tests")public class TestController {    @Autowired    private MinioService minioService;    @Autowired    private MinioPojo minioPojo;    //文件上传    @Operation(summary = "上传图片")    @PostMapping("/uploadImage")    public String aa(MultipartFile file){        String url = minioService.uploadImage(minioPojo.getBucketName(), file);        return url;    }

}

我们在MinioService中定义了uploadImage方法,传入了两个参数。一个是桶的名称,一个是文件file。(注意参数名称一定要叫file,因为现在前端默认传文件时都会叫这个名字,如果你随意的更改名字,后端会接收不到参数。)

返回文件在Minio中的地址url。(注意,只要你的容器Minio还在运行,就可以直接访问到。)

5、在MinioService中进行方法的实现。

 @Autowired    private MinioClient minioClient;    @Autowired    private MinioProperties minioProperties;    /*    * 上传文件    * */    public String uploadFile(MultipartFile file) {        try {//判断桶是否存在            boolean bucketExists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(minioProperties.getBucketName()).build());            if (!bucketExists){//                如果不存在,就创建桶                minioClient.makeBucket(MakeBucketArgs.builder().bucket(minioProperties.getBucketName()).build());            }//            本地时间,具体到年、月、日            String yyyymmdd = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));//            String uuid= UUID.randomUUID().toString();            String filename = yyyymmdd+"/"+file.getOriginalFilename();//          加一个/表示创建一个文件夹            minioClient.putObject(PutObjectArgs.builder().                    bucket(minioProperties.getBucketName()).                    object(filename).                    stream(file.getInputStream(), file.getSize(), -1).//                    文件上传的类型,如果不指定,那么每次访问时都要先下载文件        contentType(file.getContentType()).                    build());            String url= minioProperties.getUrl()+"/"+ minioProperties.getBucketName()+"/"+filename;            return url;        } catch (Exception e) {            e.printStackTrace();            throw new RuntimeException("文件上传失败");        }    }

现在,我们可以在knife4j中去测试发送信息了。

如图所示,我们发送文件成功了。返回了一个url地址,我们输入这个地址就可以直接访问到这张图片了

(注意,这里有坑。我们虽然能够上传文件,并返回了文件在Minio中的地址,但是我们现在并不能直接去访问,因为现在这个桶test默认的访问权限不够,我们要在Minio的客户端将这个桶的访问权限设为public。),创建存储桶时无法直接设置为公开访问,你需要在创建存储桶后再设置存储桶的策略来实现公开访问。这是因为MinIO遵循最小权限原则,以确保数据安全。

在进行文件的上传时,如果文件名称相同会进行覆盖。这时一般的方法为在每一次文件上传时,对文件生成一个UUID,以保证每一次上传的文件名称都不一样,以免覆盖。

也可以在Java代码中实现桶访问权限的修改,但是很麻烦。

// 设置存储桶的策略

String policyJson = "{\"Statement\"[{\"Action[\"s3:GetObject\"],\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Resource\":[\"arn:aws:s3:::" + bucketName + "/*\"],\"Sid\":\"\"}],\"Version\":\"2012-10-17\"}"; minioClient.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(bucketName).config(policyJson).build());

现在,我们就可以直接输入返回的url地址,来查看图片并下载。

我这次上传的文件类型是图片,其他的文件类型也可以上传。

6、实现文件的下载:

   /*    * 根据url 下载文件    * */    public String getObject(HttpServletRequest request, HttpServletResponse response,String url){//        将传递的url 进行切割,获取到相对于桶的文件名        String objectUrl = url.split(minioProperties.getBucketName()+"/")[1];//        文件名        String fileName = objectUrl.split("/")[1];        // 设置响应的内容类型为文件类型        response.setContentType("application/octet-stream");        // 设置响应头,指定文件名        response.setHeader("Content-Disposition", "attachment; filename=\"filename.extension\"");        // 缓冲区大小        byte[] buffer = new byte[1024];        int bytesRead;        InputStream inputStream = null;        OutputStream outputStream = null;        try{             inputStream = minioClient.getObject(GetObjectArgs.builder()                    .bucket(minioProperties.getBucketName())                    .object(objectUrl)                    .build());         /*   // 将输入流的内容复制到一个文件中            String filePath = "D://"+fileName;            Files.copy(inputStream, Path.of(filePath),                    StandardCopyOption.REPLACE_EXISTING);            return "文件下载成功,地址为"+filePath;*/            // 获取输出流             outputStream = response.getOutputStream();            // 将输入流中的数据写入输出流            while ((bytesRead = inputStream.read(buffer)) != -1) {                outputStream.write(buffer, 0, bytesRead);            }            inputStream.close();            outputStream.close();        }catch (Exception e){            e.printStackTrace();        }        return "文件下载失败";    }

这里传入的url是在Minion,成功上传文件之后返回的url地址

 假如现在在Minio中有一个url地址:http://192.168.231.110:9001/test/2023-11-05/32cc63cb-eb0c-4398-8bb8-3ac37c3a130410.png

7、实现文件的删除:

    /*    * 根据url删除文件    * */    public void deleteFile(String url) {        //        将传递的url 进行切割,获取到相对于桶的文件名        String objectUrl = url.split(minioProperties.getBucketName()+"/")[1];        try {            minioClient.removeObject(RemoveObjectArgs.builder()                    .bucket(minioProperties.getBucketName())                    .object(objectUrl)                    .build());        } catch (Exception e) {            e.printStackTrace();            throw new RuntimeException(url+"文件删除失败");        }    }

文件的删除,传入上传成功的url:http://192.168.231.110:9001/test/2023-11-05/32cc63cb-eb0c-4398-8bb8-3ac37c3a130410.png

运行这个方法是在minio中将图片该删除掉了。

总结:

我们使用minio的常用操作就是,上传、下载和删除。

这些文件都存储在我们的Linux服务器中,并不能凭空存在,所以上传时要注意把握力度。如果上传的文件太多太大的话,Linux会先撑不住的。

上一篇:原神怎么启动定位服务器?

下一篇:wwo怎么连接服务器?