linux搭建minIO对象存储服务,springBoot整合

minIO 服务搭建

1. 创建安装目录
mkdir -p /usr/local/minio
2. 进入安装目录
cd /usr/local/minio
3.下载安装包 (wget 如果下载太慢,可以手动下载并上传安装包)
wget https://dl.minio.io/server/minio/release/linux-amd64/minio

在这里插入图片描述

4.创建数据存储文件夹
mkdir -p /usr/local/minio/data
5.编辑配置文件
vim /etc/default/minio

5.1 添加内容:用户名、密码、数据存储文件、程序链接端口、web界面访问端口

MINIO_ROOT_USER="minio"
MINIO_ROOT_PASSWORD="minio@123"
MINIO_VOLUMES=" /usr/local/minio/data"
MINIO_OPTS="--address 0.0.0.0:9000"
MINIO_OPTS1="--console-address 0.0.0.0:19001"
6.添加开机自启动配置

编辑配置文件文件

vim /etc/systemd/system/minio.service

添加配置文件内容 (主意启动器路径,自定义服务配置文件路径,以及连接端口要与配置文件里的对应)

[Unit]
Description=MinIO
Documentation=https://docs.min.io
Wants=network-online.target
After=network-online.target
AssertFileIsExecutable=/usr/local/minio/minio

[Service]
WorkingDirectory=/usr/local/minio
ProtectProc=invisible

EnvironmentFile=/etc/default/minio
ExecStartPre=/bin/bash -c "if [ -z \"${MINIO_VOLUMES}\" ]; then echo \"Variable MINIO_VOLUMES not set in /etc/default/minio\"; exit 1; fi"
ExecStart=/usr/local/minio/minio server --address 0.0.0.0:9000 $MINIO_OPTS  $MINIO_OPTS1 $MINIO_VOLUMES

# Let systemd restart this service always
Restart=always

# Specifies the maximum file descriptor number that can be opened by this process
LimitNOFILE=65536

# Specifies the maximum number of threads this process can create
TasksMax=infinity

# Disable timeout logic and wait until process is stopped
TimeoutStopSec=infinity
SendSIGKILL=no

[Install]
WantedBy=multi-user.target
7. 启动服务
#加载配置
systemctl daemon-reload
#添加启动器权限
chmod +x /usr/local/minio/minio
#启动minio
systemctl start minio.service
#开启开机自启
systemctl enable minio.service

查看服务

ps -ef |grep minio

在这里插入图片描述

8.验证服务
http://ip:19001/login

在这里插入图片描述
通过配置的账号密码登录
在这里插入图片描述

9.常用命令
systemctl start minio.service   #启动minio服务
systemctl stop minio.service   #停止minio服务
systemctl restart minio.service   #重新启动服务
systemctl status minio.service   #查看服务当前状态
systemctl enable minio.service   #设置开机自启动
systemctl disable minio.service   #停止开机自启动
10.目录
安装目录:/usr/local/minio
数据保存目录:/usr/local/minio/data
配置文件目录:/etc/default/minio
启动配置文件存放目录:vim /etc/systemd/system/minio.service

SpringBoot 整合

1.添加依赖

比较新的版本 最新到8.5.5 ,更多版本可以到maven仓库找
https://mvnrepository.com/artifact/io.minio/minio

        <!-- https://mvnrepository.com/artifact/io.minio/minio -->
        <dependency>
            <groupId>io.minio</groupId>
            <artifactId>minio</artifactId>
            <version>8.5.3</version>
        </dependency>
2.添加yml配置
minio:
  endpoint: http://127.0.0.1:9000 #Minio服务所在地址
  bucketName: test #存储桶名称
  accessKey: minioadmin #访问的key
  secretKey: minioadmin #访问的秘钥
3.MinioConfig.class配置类
@Data
@Configuration
@ConfigurationProperties(prefix = "minio")
public class MinioConfig {

    private String endpoint;
    private String accessKey;
    private String secretKey;
    private String bucketName;

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

4.minio工具类
import com.alibaba.nacos.common.utils.UuidUtils;
import com.system.common.utils.RandomIdUtil;
import com.system.iotmanagement.config.MinioConfig;
import io.minio.*;
import io.minio.http.Method;
import io.minio.messages.Bucket;
import io.minio.messages.Item;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.FastByteArrayOutputStream;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.util.UriUtils;

import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

@Component
@Slf4j
public class MinioUtil {
    @Autowired
    private MinioConfig prop;

    @Resource
    private MinioClient minioClient;

    /**
     * 查看存储bucket是否存在
     * @return boolean
     */
    public Boolean bucketExists(String bucketName) {
        Boolean found;
        try {
            found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return found;
    }

/**
    * 创建存储bucket
    * @return Boolean
    */
   public Boolean makeBucket(String bucketName) {
       try {
           if (!bucketExists(bucketName)) {
               minioClient.makeBucket(MakeBucketArgs.builder()
                       .bucket(bucketName)
                       .build());
               String policyJson = "{\n" +
                       "\t\"Version\": \""+new SimpleDateFormat("yyyy-mm-dd").format(System.currentTimeMillis())+"\",\n" +
                       "\t\"Statement\": [{\n" +
                       "\t\t\"Effect\": \"Allow\",\n" +
                       "\t\t\"Principal\": {\n" +
                       "\t\t\t\"AWS\": [\"*\"]\n" +
                       "\t\t},\n" +
                       "\t\t\"Action\": [\"s3:GetBucketLocation\", \"s3:ListBucket\", \"s3:ListBucketMultipartUploads\"],\n" +
                       "\t\t\"Resource\": [\"arn:aws:s3:::" + bucketName + "\"]\n" +
                       "\t}, {\n" +
                       "\t\t\"Effect\": \"Allow\",\n" +
                       "\t\t\"Principal\": {\n" +
                       "\t\t\t\"AWS\": [\"*\"]\n" +
                       "\t\t},\n" +
                       "\t\t\"Action\": [\"s3:AbortMultipartUpload\", \"s3:DeleteObject\", \"s3:GetObject\", \"s3:ListMultipartUploadParts\", \"s3:PutObject\"],\n" +
                       "\t\t\"Resource\": [\"arn:aws:s3:::" + bucketName + "/*\"]\n" +
                       "\t}]\n" +
                       "}\n";
               minioClient.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(bucketName).config(policyJson).build());
               log.info("buckets:【{}】,创建[readwrite]策略成功!", bucketName);
           } else {
               log.info("minio bucket->>>【{}】already exists", bucketName);
           }
       } catch (Exception e) {
           e.printStackTrace();
           return false;
       }
       return true;
   }

    
    /**
     * 删除存储bucket
     * @return Boolean
     */
    public Boolean removeBucket(String bucketName) {
        try {
            minioClient.removeBucket(RemoveBucketArgs.builder()
                    .bucket(bucketName)
                    .build());
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }
        return true;
    }
    /**
     * 获取全部bucket
     */
    public List<Bucket> getAllBuckets() {
        try {
            List<Bucket> buckets = minioClient.listBuckets();
            return buckets;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 文件上传
     *
     * @param file 文件
     * @return Boolean
     */
    public String upload(MultipartFile file) {
        String originalFilename = file.getOriginalFilename();
        if (StringUtils.isBlank(originalFilename)){
            throw new RuntimeException();
        }
        String fileName = UuidUtils.generateUuid() + originalFilename.substring(originalFilename.lastIndexOf("."));
        String objectName = RandomIdUtil.getyyyyMMddString() + "/" + fileName;
        try {
            PutObjectArgs objectArgs = PutObjectArgs.builder().bucket(prop.getBucketName()).object(objectName)
                    .stream(file.getInputStream(), file.getSize(), -1).contentType(file.getContentType()).build();
            //文件名称相同会覆盖
            minioClient.putObject(objectArgs);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return  objectName;
    }

    /**
     * 预览图片
     * @param fileName
     * @return
     */
    public String preview(String fileName){
        // 查看文件地址
        GetPresignedObjectUrlArgs build = new GetPresignedObjectUrlArgs().builder().bucket(prop.getBucketName()).object(fileName).method(Method.GET).build();
        try {
            String url = minioClient.getPresignedObjectUrl(build);
            return url;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 文件下载
     * @param fileName 文件名称
     * @param res response
     * @return Boolean
     */
    public void download(String fileName, HttpServletResponse res) {
        GetObjectArgs objectArgs = GetObjectArgs.builder().bucket(prop.getBucketName())
                .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=" + UriUtils.encode(fileName, StandardCharsets.UTF_8));
                try (ServletOutputStream stream = res.getOutputStream()){
                    stream.write(bytes);
                    stream.flush();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 查看文件对象
     * @return 存储bucket内文件对象信息
     */
    public List<Item> listObjects() {
        Iterable<Result<Item>> results = minioClient.listObjects(
                ListObjectsArgs.builder().bucket(prop.getBucketName()).build());
        List<Item> items = new ArrayList<>();
        try {
            for (Result<Item> result : results) {
                items.add(result.get());
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return items;
    }

    /**
     * 删除
     * @param fileName
     * @return
     * @throws Exception
     */
    public boolean remove(String fileName){
        try {
            minioClient.removeObject( RemoveObjectArgs.builder().bucket(prop.getBucketName()).object(fileName).build());
        }catch (Exception e){
            return false;
        }
        return true;
    }
}

生成时间字符串的工具类,(可以自己另外引用其他的)

import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.symmetric.AES;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Random;

public class RandomIdUtil {

    /**
     * 生成随机ID:当前年月日时分秒毫秒 +五位随机数
     */
    public static String getRandomID(String businessCode) {
        String str  = new SimpleDateFormat("yyyyMMddHHmmssSS").format(new Date());
        Random random = new Random();
        int rannum = (int) (random.nextDouble() * (99999 - 10000 + 1)) + 10000;// 获取5位随机数
        return businessCode+str + rannum;// 当前时间
    }

    public static String getyyyyMMddHHString() {
        return new SimpleDateFormat("yyyyMMddHH").format(new Date());
    }

    public static String getyyyyMMddString() {
        return new SimpleDateFormat("yyyyMMdd").format(new Date());
    }

}

5. 文件处理接口


@Api(tags = "文件相关接口")
@Slf4j
@RestController
@RequestMapping(value = "product/file")
public class FileController {


    @Autowired
    private MinioUtil minioUtil;
    @Autowired
    private MinioConfig prop;

    @ApiOperation(value = "查看存储bucket是否存在")
    @GetMapping("/bucketExists")
    public R bucketExists(@RequestParam("bucketName") String bucketName) {
        return R.ok().put("bucketName",minioUtil.bucketExists(bucketName));
    }

    @ApiOperation(value = "创建存储bucket")
    @GetMapping("/makeBucket")
    public R makeBucket(String bucketName) {
        return R.ok().put("bucketName",minioUtil.makeBucket(bucketName));
    }

    @ApiOperation(value = "删除存储bucket")
    @GetMapping("/removeBucket")
    public R removeBucket(String bucketName) {
        return R.ok().put("bucketName",minioUtil.removeBucket(bucketName));
    }

    @ApiOperation(value = "获取全部bucket")
    @GetMapping("/getAllBuckets")
    public R getAllBuckets() {
        List<Bucket> allBuckets = minioUtil.getAllBuckets();
        return R.ok().put("allBuckets",allBuckets);
    }

    @ApiOperation(value = "文件上传返回url")
    @PostMapping("/upload")
    public R upload(@RequestParam("file") MultipartFile file) {
        String objectName = minioUtil.upload(file);
        if (null != objectName) {
            return R.ok().put("url",(prop.getEndpoint() + "/" + prop.getBucketName() + "/" + objectName));
        }
        return R.error();
    }

    @ApiOperation(value = "图片/视频预览")
    @GetMapping("/preview")
    public R preview(@RequestParam("fileName") String fileName) {
        return R.ok().put("filleName",minioUtil.preview(fileName));
    }

    @ApiOperation(value = "文件下载")
    @GetMapping("/download")
    public R download(@RequestParam("fileName") String fileName, HttpServletResponse res) {
        minioUtil.download(fileName,res);
        return R.ok();
    }

    @ApiOperation(value = "删除文件", notes = "根据url地址删除文件")
    @PostMapping("/delete")
    public R remove(String url) {
        String objName = url.substring(url.lastIndexOf(prop.getBucketName()+"/") + prop.getBucketName().length()+1);
        minioUtil.remove(objName);
        return R.ok().put("objName",objName);
    }

}

基本操作和可能遇到的问题

1.存储bucket 的两种方式

1.客户端手动创建
在这里插入图片描述
2.代码创建,见工具类和接口方法

可能遇到的问题

当文件上传之后比如一张图片,直接通过图片路径访问报一下错误
在这里插入图片描述
这是因为浏览器打开没有权限
解决办法,默认显示的是n/a,设置minio代理权限,选择对应的桶,将其代理权限也设置为公有
在这里插入图片描述
就可以成功访问了

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
整合MinioSpring Boot可以通过以下几个步骤完成: 1. 首先,需要在pom.xml文件中添加Minio的依赖项。你可以使用以下代码片段添加依赖项: ```xml <dependency> <groupId>io.minio</groupId> <artifactId>minio</artifactId> <version>8.4.3</version> </dependency> ``` 2. 接下来,在application.yml(或application.properties)文件中配置Minio的连接信息。你需要提供Minio服务端的地址、访问密钥和存储桶名称。以下是一个示例: ```yaml minio: url: 129.0.0.1:9000 access-key: minioadmin secret-key: minioadmin bucket-name: ding_server ``` 3. 最后,在你的代码中使用Minio客户端库进行操作。你可以根据需要使用Minio的API来上传、下载和管理对象。以下是一个使用Minio客户端库的示例: ```java import io.minio.MinioClient; import io.minio.errors.MinioException; // 创建Minio客户端 MinioClient minioClient = new MinioClient("http://localhost:9000", "minioadmin", "minioadmin"); // 上传对象到Minio存储桶 minioClient.putObject("your-bucket-name", "your-object-name", "/path/to/your-file"); // 下载对象从Minio存储桶 minioClient.getObject("your-bucket-name", "your-object-name", "/path/to/save/downloaded-file"); // 列出Minio存储桶中的所有对象 Iterable<Result<Item>> results = minioClient.listObjects("your-bucket-name"); for (Result<Item> result : results) { Item item = result.get(); System.out.println(item.objectName()); } // 删除Minio存储桶中的对象 minioClient.removeObject("your-bucket-name", "your-object-name"); ``` 以上就是在Spring Boot整合Minio的基本步骤。你可以根据具体需求进行进一步的操作和配置。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [springboot整合minio](https://blog.csdn.net/qq_36090537/article/details/128100423)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] - *3* [SpringBoot整合Minio](https://blog.csdn.net/weixin_46573014/article/details/128476327)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值