SpringBoot整合Minio实现上传文件的完整步骤记录

目录
  • Minio
  • 安装 Minio
    • 使用docker安装
      • 拉取镜像
      • 启动
      • 使用9000端口 登录控制台
      • 创建存储桶
    • 设置桶权限
  • 创建 Java 客户端
    • 依赖
    • 配置文件
    • 配置文件配置类
    • 创建 minio 客户端
    • 文件地址返回路径实体类
    • 上传文件工具类
    • 测试上传文件 Controller
  • 测试上传
    • 控制台也可以看到上传的视频
  • 总结

Minio

上传文件如果不使用云服务的话,需要本地搭建,一般选择 FastDFS 但是 FastDFS 安装比较复杂,今天了解一款安装使用更简单的存储系统 MinIO

MinIO 是一款高性能、分布式的对象存储系统. 它是一款软件产品, 可以100%的运行在标准硬件。即X86等低成本机器也能够很好的运行MinIO。

MinIO与传统的存储和其他的对象存储不同的是:它一开始就针对性能要求更高的私有云标准进行软件架构设计。因为MinIO一开始就只为对象存储而设计。所以他采用了更易用的方式进行设计,它能实现对象存储所需要的全部功能,在性能上也更加强劲,它不会为了更多的业务功能而妥协,失去MinIO的易用性、高效性。 这样的结果所带来的好处是:它能够更简单的实现局有弹性伸缩能力的原生对象存储服务。

MinIO在传统对象存储用例(例如辅助存储,灾难恢复和归档)方面表现出色。同时,它在机器学习、大数据、私有云、混合云等方面的存储技术上也独树一帜。当然,也不排除数据分析、高性能应用负载、原生云的支持。

在中国:阿里巴巴、腾讯、百度、中国联通、华为、中国移动等等9000多家企业也都在使用MinIO产品

安装 Minio

使用docker安装

拉取镜像

docker pull minio/minio

启动

docker run -p 9000:9000 -p 9001:9001 -d --name minio -v /opt/docker/minio/data:/data -v /opt/docker/minio/config:/root/.minio -e "MINIO_ROOT_USER=minio" -e "MINIO_ROOT_PASSWORD=minio@123456" minio/minio server /data --console-address ":9000" --address ":9001"

使用9000端口 登录控制台

创建存储桶

设置桶权限

创建 Java 客户端

依赖

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
        <exclusions>
            <exclusion>
                <groupId>org.junit.vintage</groupId>
                <artifactId>junit-vintage-engine</artifactId>
            </exclusion>
        </exclusions>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-configuration-processor</artifactId>
        <optional>true</optional>
    </dependency>

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>

    <!-- minio依赖       -->
    <dependency>
        <groupId>io.minio</groupId>
        <artifactId>minio</artifactId>
        <version>8.2.1</version>
    </dependency>

    <!-- hutool工具类       -->
    <dependency>
        <groupId>cn.hutool</groupId>
        <artifactId>hutool-all</artifactId>
        <version>5.1.2</version>
    </dependency>

    <!-- 压缩图片       -->
    <dependency>
        <groupId>net.coobird</groupId>
        <artifactId>thumbnailator</artifactId>
        <version>0.4.8</version>
    </dependency>

    <!--    工具类依赖    -->
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
        <version>3.12.0</version>
    </dependency>

    <dependency>
        <groupId>com.github.davidcarboni</groupId>
        <artifactId>encrypted-</artifactId>
        <version>1.0.0</version>
    </dependency>
</dependencies>

配置文件

spring:
  application:
    name: minio-demo
  servlet:
    multipart:
      max-file-size: 20MB
      max-request-size: 200MB
server:
  port: 8088

minio:
  endpoint: http://你的ip:9001
  accessKey: minio
  secretKey: minio@123456
  nginxHost: http://你的域名

配置文件配置类

package com.sqm.minio_demo.config;

import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

@ConfigurationProperties(prefix = "minio")
@Component
@Data
public class MinioProperties {
    /**
     * 连接地址
     */
    private String endpoint;
    /**
     * 用户名
     */
    private String accessKey;
    /**
     * 密码
     */
    private String secretKey;
    /**
     * 域名
     */
    private String nginxHost;
}

创建 minio 客户端

package com.sqm.minio_demo.config;

import io.minio.MinioClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
@EnableConfigurationProperties(MinioProperties.class)
public class MinioConfig {

    @Autowired
    private MinioProperties minioProperties;

    @Bean
    public MinioClient minioClient(){
        return MinioClient.builder()
                .endpoint(minioProperties.getEndpoint())
                .credentials(minioProperties.getAccessKey(),minioProperties.getSecretKey())
                .build();
    }
}

文件地址返回路径实体类

package com.sqm.minio_demo.entity;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class UploadResponse {

    private String minIoUrl;

    private String nginxUrl;
}

上传文件工具类

package com.sqm.minio_demo.util;

import cn.hutool.core.date.DateUtil;
import com.sqm.minio_demo.config.MinioProperties;
import com.sqm.minio_demo.entity.UploadResponse;
import io.minio.*;
import io.minio.errors.*;
import io.minio.messages.Bucket;
import lombok.extern.slf4j.Slf4j;
import net.coobird.thumbnailator.Thumbnails;

import org.apache.commons.fileupload.FileItem;

import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.Optional;
import java.util.Random;

@Component
@Slf4j
public class MinioUtil {

    @Autowired
    private MinioProperties minioProperties;

    @Autowired
    private MinioClient minioClient;

    private final Long maxSize = (long) (1024 * 1024);

    /**
     * 创建bucket
     */
    public void createBucket(String bucketName) throws Exception {
        if (!minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())) {
            minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
        }
    }

    /**
     * 上传文件
     */
    public UploadResponse uploadFile(MultipartFile file, String bucketName) throws Exception {
        //判断文件是否为空
        if (null == file || 0 == file.getSize()) {
            return null;
        }
        //判断存储桶是否存在  不存在则创建
        createBucket(bucketName);
        //文件名
        String originalFilename = file.getOriginalFilename();
        //新的文件名 = 时间戳_随机数.后缀名
        assert originalFilename != null;
        long now = System.currentTimeMillis() / 1000;
        String fileName = DateUtil.format(DateUtil.date(),"yyyyMMdd")+"_"+ now + "_" + new Random().nextInt(1000) +
                originalFilename.substring(originalFilename.lastIndexOf("."));
        //开始上传
        log.info("file压缩前大小:{}",file.getSize());
        if (file.getSize() > maxSize) {
            FileItemFactory fileItemFactory = new DiskFileItemFactory();
            FileItem fileItem = fileItemFactory.createItem(fileName, "text/plain", true, fileName);
            OutputStream outputStream = fileItem.getOutputStream();
            Thumbnails.of(file.getInputStream()).scale(1f).outputFormat(originalFilename.substring(originalFilename.lastIndexOf(".")+1)).outputQuality(0.25f).toOutputStream(outputStream);
            file = new CommonsMultipartFile(fileItem);
        }
        log.info("file压缩后大小:{}",file.getSize());
        minioClient.putObject(
                PutObjectArgs.builder().bucket(bucketName).object(fileName).stream(
                        file.getInputStream(), file.getSize(), -1)
                        .contentType(file.getContentType())
                        .build());
        String url = minioProperties.getEndpoint() + "/" + bucketName + "/" + fileName;
        String urlHost = minioProperties.getNginxHost() + "/" + bucketName + "/" + fileName;
        return new UploadResponse(url, urlHost);
    }

    /**
     * 获取全部bucket
     *
     * @return
     */
    public List<Bucket> getAllBuckets() throws Exception {
        return minioClient.listBuckets();
    }

    /**
     * 根据bucketName获取信息
     *
     * @param bucketName bucket名称
     */
    public Optional<Bucket> getBucket(String bucketName) throws IOException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException, InvalidResponseException, InternalException, ErrorResponseException, ServerException, XmlParserException, ServerException {
        return minioClient.listBuckets().stream().filter(b -> b.name().equals(bucketName)).findFirst();
    }

    /**
     * 根据bucketName删除信息
     *
     * @param bucketName bucket名称
     */
    public void removeBucket(String bucketName) throws Exception {
        minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());
    }

    /**
     * 获取⽂件外链
     *
     * @param bucketName bucket名称
     * @param objectName ⽂件名称
     * @param expires    过期时间 <=7
     * @return url
     */
    public String getObjectURL(String bucketName, String objectName, Integer expires) throws Exception {
        return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().bucket(bucketName).object(objectName).expiry(expires).build());
    }

    /**
     * 获取⽂件
     *
     * @param bucketName bucket名称
     * @param objectName ⽂件名称
     * @return ⼆进制流
     */
    public InputStream getObject(String bucketName, String objectName) throws Exception {
        return minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(objectName).build());
    }

    /**
     * 上传⽂件
     *
     * @param bucketName bucket名称
     * @param objectName ⽂件名称
     * @param stream     ⽂件流
     * @throws Exception https://docs.minio.io/cn/java-minioClient-api-reference.html#putObject
     */
    public void putObject(String bucketName, String objectName, InputStream stream) throws
            Exception {
        minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(objectName).stream(stream, stream.available(), -1).contentType(objectName.substring(objectName.lastIndexOf("."))).build());
    }

    /**
     * 上传⽂件
     *
     * @param bucketName  bucket名称
     * @param objectName  ⽂件名称
     * @param stream      ⽂件流
     * @param size        ⼤⼩
     * @param contextType 类型
     * @throws Exception https://docs.minio.io/cn/java-minioClient-api-reference.html#putObject
     */
    public void putObject(String bucketName, String objectName, InputStream stream, long
            size, String contextType) throws Exception {
        minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(objectName).stream(stream, size, -1).contentType(contextType).build());
    }

    /**
     * 获取⽂件信息
     *
     * @param bucketName bucket名称
     * @param objectName ⽂件名称
     * @throws Exception https://docs.minio.io/cn/java-minioClient-api-reference.html#statObject
     */
    public StatObjectResponse getObjectInfo(String bucketName, String objectName) throws Exception {
        return minioClient.statObject(StatObjectArgs.builder().bucket(bucketName).object(objectName).build());
    }

    /**
     * 删除⽂件
     *
     * @param bucketName bucket名称
     * @param objectName ⽂件名称
     * @throws Exception https://docs.minio.io/cn/java-minioClient-apireference.html#removeObject
     */
    public void removeObject(String bucketName, String objectName) throws Exception {
        minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(objectName).build());
    }

    /***
     * 上传视频
     * @param file
     * @param bucketName
     * @return
     * @throws Exception
     */
    public UploadResponse uploadVideo(MultipartFile file, String bucketName) throws Exception {
        //判断文件是否为空
        if (null == file || 0 == file.getSize()) {
            return null;
        }
        //判断存储桶是否存在  不存在则创建
        createBucket(bucketName);
        //文件名
        String originalFilename = file.getOriginalFilename();
        //新的文件名 = 时间戳_随机数.后缀名
        assert originalFilename != null;
        long now = System.currentTimeMillis() / 1000;
        String fileName = DateUtil.format(DateUtil.date(),"yyyyMMdd")+"_"+ now + "_" + new Random().nextInt(1000) +
                originalFilename.substring(originalFilename.lastIndexOf("."));
        //开始上传
        log.info("file大小:{}",file.getSize());
        minioClient.putObject(
                PutObjectArgs.builder().bucket(bucketName).object(fileName).stream(
                        file.getInputStream(), file.getSize(), -1)
                        .contentType("video/mp4")
                        .build());
        String url = minioProperties.getEndpoint() + "/" + bucketName + "/" + fileName;
        String urlHost = minioProperties.getNginxHost() + "/" + bucketName + "/" + fileName;
        return new UploadResponse(url, urlHost);
    }
}

测试上传文件 Controller

package com.sqm.minio_demo.controller;

import com.sqm.minio_demo.entity.ResultData;
import com.sqm.minio_demo.entity.UploadResponse;
import com.sqm.minio_demo.util.MinioUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

@RestController
@Slf4j
public class TestController {

    @Autowired
    private MinioUtil minioUtil;

    /**
     * @author: xx
     * @date: 2022/5/25 15:32
     * @description: 上传文件
     */
    @PostMapping("/upload")
    public ResultData minioUpload(@RequestParam(value = "file") MultipartFile file){
        UploadResponse response = null;
        try {
            response = minioUtil.uploadFile(file, "bucket01");
        } catch (Exception e) {
            log.error("上传失败",e);
        }
        return ResultData.ok(response);
    }

    /**
     * @author: xx
     * @date: 2022/5/25 15:32
     * @description: 上传视频
     */
    @PostMapping("/uploadVideo")
    public ResultData uploadVideo(@RequestParam(value = "file") MultipartFile file){
        UploadResponse response = null;
        try {
            response = minioUtil.uploadVideo(file, "video-test");
        } catch (Exception e) {
            log.error("上传失败",e);
        }
        return ResultData.ok(response);
    }
}

测试上传

控制台也可以看到上传的视频

总结

到此这篇关于SpringBoot整合Minio实现上传文件的文章就介绍到这了,更多相关SpringBoot整合Minio上传文件内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • SpringBoot整合MinIO实现文件上传的方法详解

    目录 前言 1. MinIO 简介 2. MinIO 安装 3. 整合 Spring Boot 4. 配置nginx 5. 小结 前言 现在 OSS 服务算是一个基础服务了,很多云服务厂商都有提供这样的服务,价格也不贵,松哥自己的网站用的就是类似的服务. 不过对于中小公司来说,除了购买 OSS 服务之外,也可以自己搭建专业的文件服务器,自己搭建专门的文件服务器的话,曾经比较专业的做法是 FastDFS,松哥之前也专门为之录过视频发在 B 站上,感兴趣的小伙伴可以自行查看.不过 FastDFS 搭

  • springboot整合minio实现文件上传与下载且支持链接永久访问

    目录 1.minio部署 2.项目搭建 3.文件上传 4.文件下载 5.文件永久链接下载 1.minio部署 1.1 拉取镜像 docker pull minio/minio 1.2 创建数据目录 mkdir -p /home/guanz/minio mkdir -p /home/guanz/minio/midata 1.3 启动minio docker run -d -p 9000:9000 -p 9001:9001 --restart=always -e MINIO_ACCESS_KEY=g

  • SpringBoot整合Minio实现上传文件的完整步骤记录

    目录 Minio 安装 Minio 使用docker安装 拉取镜像 启动 使用9000端口 登录控制台 创建存储桶 设置桶权限 创建 Java 客户端 依赖 配置文件 配置文件配置类 创建 minio 客户端 文件地址返回路径实体类 上传文件工具类 测试上传文件 Controller 测试上传 控制台也可以看到上传的视频 总结 Minio 上传文件如果不使用云服务的话,需要本地搭建,一般选择 FastDFS 但是 FastDFS 安装比较复杂,今天了解一款安装使用更简单的存储系统 MinIO M

  • springboot整合vue实现上传下载文件

    springboot整合vue实现上传下载文件,供大家参考,具体内容如下 环境 springboot 1.5.x 完整代码下载:springboot整合vue实现上传下载 1.上传下载文件api文件 设置上传路径,如例子: private final static String rootPath = System.getProperty("user.home")+File.separator+fileDir+File.separator; api接口: 下载url示例:http://l

  • springboot以FTP方式上传文件到远程服务器

    一.html代码   <div class="layui-form-item"> <label class="layui-form-label">上传附件:</label> <div class="layui-input-block doc-litpic"> <button type="button" name="avatar" class="

  • Node.js连接mongo数据库上传文件的方法步骤

    目录 效果 初始化 model 下创建index.js用于连接数据库时的信息 修改app.js文件里的信息 router下修改user.js文件 创建上传文件保存文件夹 在public下新建一个index.html 用于请求时的主页面 效果 初始化 创建项目文件夹mondo-express 安装包 npm i express-generator -g(作用一键生成项目列表) 在项目文件夹mondo-express用终端打开输入npx express-generator自动生成项目目录 安装包 终

  • SpringBoot中的multipartResolver上传文件配置

    目录 multipartResolver上传文件配置 1.gradle配置 2.注册Bean SpringBoot MultipartResolver的坑 解决方案 multipartResolver上传文件配置 1.gradle配置 compile ('commons-io:commons-io:1.4') compile('commons-fileupload:commons-fileupload:1.2.1') 2.注册Bean @Bean(name = "multipartResolve

  • Vue中通过minio上传文件的详细步骤

    目录 1.minio的安装 2.minio.js文件 2.1连接minio 2.2通过stream流上传 2.3通过带预签名的url上传(最好是minio设置了链接永久访问) 2.4删除对象 补充:base64转blob 3.获取时间方法 4.minio设置链接永久访问(客户端) 5.解决跨域问题 6.存储大小限制问题 7.minio官方文档 8.minio设置链接永久访问(其他方法) 总结 在Vue中minio上传文件(stream流和链接) 1.minio的安装 直接使用npm或者cnpm下

  • Springboot整合minio实现文件服务的教程详解

    首先pom文件引入相关依赖 <!--minio--> <dependency> <groupId>io.minio</groupId> <artifactId>minio</artifactId> <version>3.0.10</version> </dependency> springboot配置文件application.yml 里配置minio信息 #minio配置 minio: endpo

  • SpringBoot整合Minio文件存储

    目录 背景 Minio安装部署 配置pom文件--h2> 配置yml文件 Minio工具类 初始化client 上传文件 下载文件 删除文件 背景 公司的开发框架集成了附件本地存储,阿里云,华为云等,现项目有要求附件存储与应用部署环境不能是同一台服务器,也不能使用云存储,经过技术选型后决定框架整合minio,将minio部署在另一台服务器开通外网端口即可解决问题 Minio安装部署 下载minio安装部署包,创建对应配置文件,这里提供一个整合后的压缩包 下载地址:http://xiazai.jb

随机推荐