ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

oss对象存储-minio初体验

2022-01-11 11:03:49  阅读:406  来源: 互联网

标签:初体验 minio oss param bucketName import public String


官方文档地址

https://docs.min.io/
http://docs.minio.org.cn/docs/

JavaSDK: https://github.com/minio/minio-java

什么是 MinIO?

Minio 是个基于 Golang 编写的开源对象存储套件,基于Apache License v2.0开源协议,虽然轻量,却拥有着不错的性能。它兼容亚马逊S3云存储服务接口。可以很简单的和其他应用结合使用,例如 NodeJS、Redis、MySQL等。

MinIO 的应用场景

MinIO 的应用场景除了可以作为私有云的对象存储服务来使用,也可以作为云对象存储的网关层,无缝对接 Amazon S3 或者 MicroSoft Azure 。

minio特点

  • 高性能:
    作为一款高性能存储,在标准硬件条件下,其读写速率分别可以达到 55Gb/s35Gb/s。并而 MinIO 支持一个对象文件可以是任意大小,从几kb到最大5T不等。

  • 可扩展:
    不同MinIO集群可以组成联邦,并形成一个全局的命名空间,并且支持跨越多个数据中心。

  • 云原生:
    容器化、基于K8S的编排、多租户支持。

  • Amazon S3兼容:
    使用 Amazon S3 v2 / v4 API。可以使用Minio SDK,Minio Client,AWS SDK 和 AWS CLI 访问Minio服务器。

  • 可对接多种后端存储:
    除了Minio自己的文件系统,还支持 DAS、 JBODs、NAS、Google云存储和 Azure Blob存储。

window安装minio服务(本地)

1.下载地址
https://dl.min.io/server/minio/release/windows-amd64/minio.exe

2.进入下载目录,调用cmd窗口,并执行如下命令:
.\minio.exe server F:\minio\photos

3.访问:http://127.0.0.1:9000/,进入minio服务器登录页面

默认账号密码均为:minioadmin

minio之java应用

1.pom引入jar包依赖

<!-- minio 文件服务客户端 -->
        <dependency>
            <groupId>io.minio</groupId>
            <artifactId>minio</artifactId>
            <version>6.0.11</version>
        </dependency>
        <!--hutool-->
        <dependency>
            <groupId>cn.hutool</groupId>
            <artifactId>hutool-all</artifactId>
            <version>5.1.1</version>
        </dependency>

2.添加配置文件

  • url:minio服务器的接口地址,不是访问地址
  • accessKey/secretKey:登录minio系统,新建Service Accounts
config:
  minio:
    url: http://192.168.1.114:9000
    accessKey: MMXHB6HAXWCCVG8ULAVK
    secretKey: 7J7v99N0LubbzshG2UmOrID9j2PNMG5mpCnBENv1

3.注册MinioClient

package cn.cjq.config;

import io.minio.MinioClient;
import lombok.Data;
import lombok.SneakyThrows;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
//import org.springframework.cloud.context.config.annotation.RefreshScope;

@Data
@Configuration
@ConfigurationProperties(prefix = "config.minio")
public class MinioConfig {
    /**
     * minio 服务地址 http://ip:port
     */
    private String url;

    /**
     * 用户名
     */
    private String accessKey;

    /**
     * 密码
     */
    private String secretKey;

    @SneakyThrows
    @Bean
//    @RefreshScope
    public MinioClient minioClient(){
        return new MinioClient(url, accessKey, secretKey);
    }
}

4.minio工具类

package cn.cjq.util;

import cn.cjq.entity.MinioItem;
import io.minio.MinioClient;
import io.minio.ObjectStat;
import io.minio.Result;
import io.minio.messages.Bucket;
import io.minio.messages.Item;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 * minio工具类
 *
 * @author lvlinguang
 * @date 2022-01-07 12:26
 * @see “http://docs.minio.org.cn/docs/master/java-client-api-reference”
 */
@Component
public class MinioUtils {

    @Autowired
    private MinioClient client;

    /**
     * 创建bucket
     *
     * @param bucketName
     */
    @SneakyThrows
    public void createBucket(String bucketName) {
        if (!client.bucketExists(bucketName)) {
            client.makeBucket(bucketName);
        }
    }

    /**
     * 获取所有bucket
     *
     * @return
     */
    @SneakyThrows
    public List<Bucket> listAllBuckets() {
        return client.listBuckets();
    }

    /**
     * bucket详情
     *
     * @param bucketName 名称
     * @return
     */
    @SneakyThrows
    public Optional<Bucket> getBucket(String bucketName) {
        return client.listBuckets().stream().filter(b -> b.name().equals(bucketName)).findFirst();
    }

    /**
     * 删除bucket
     *
     * @param bucketName 名称
     */
    @SneakyThrows
    public void removeBucket(String bucketName) {
        client.removeBucket(bucketName);
    }

    /**
     * 上传文件
     *
     * @param bucketName bucket名称
     * @param objectName 文件名称
     * @param stream     文件流
     * @throws Exception
     */
    @SneakyThrows
    public void uploadFile(String bucketName, String objectName, InputStream stream) throws Exception {
        this.uploadFile(bucketName, objectName, stream, (long) stream.available(), "application/octet-stream");
    }

    /**
     * 上传文件
     *
     * @param bucketName  bucket名称
     * @param objectName  文件名称
     * @param stream      文件流
     * @param size        大小
     * @param contextType 类型
     * @throws Exception
     */
    @SneakyThrows
    public void uploadFile(String bucketName, String objectName, InputStream stream, long size, String contextType) throws Exception {
        //如果bucket不存在,则创建
        this.createBucket(bucketName);
        client.putObject(bucketName, objectName, stream, size, null, null, contextType);
    }

    /**
     * 获取文件
     *
     * @param bucketName bucket名称
     * @param objectName 文件名称
     * @return
     */
    @SneakyThrows
    public InputStream getFile(String bucketName, String objectName) {
        return client.getObject(bucketName, objectName);
    }

    /**
     * 根据文件前置查询文件
     *
     * @param bucketName bucket名称
     * @param prefix     前缀
     * @param recursive  是否递归查询
     * @return
     */
    @SneakyThrows
    public List<MinioItem> listAllFileByPrefix(String bucketName, String prefix, boolean recursive) {
        List<MinioItem> objectList = new ArrayList<>();
        Iterable<Result<Item>> objectsIterator = client
                .listObjects(bucketName, prefix, recursive);
        while (objectsIterator.iterator().hasNext()) {
            objectList.add(new MinioItem(objectsIterator.iterator().next().get()));
        }
        return objectList;
    }

    /**
     * 删除文件
     *
     * @param bucketName bucket名称
     * @param objectName 文件名称
     */
    @SneakyThrows
    public void removeFile(String bucketName, String objectName) {
        client.removeObject(bucketName, objectName);
    }

    /**
     * 获取文件外链
     *
     * @param bucketName bucket名称
     * @param objectName 文件名称
     * @param expires    过期时间 <=7
     * @return
     */
    @SneakyThrows
    public String getFileURL(String bucketName, String objectName, Integer expires) {
        return client.presignedGetObject(bucketName, objectName, expires);
    }

    /**
     * 获取文件信息
     *
     * @param bucketName bucket名称
     * @param objectName 文件名称
     * @return
     */
    @SneakyThrows
    public ObjectStat getFileInfo(String bucketName, String objectName) {
        return client.statObject(bucketName, objectName);
    }
}
View Code

5.文件操作类

package cn.cjq.util;

import cn.cjq.entity.MinioObject;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.InputStream;
import java.time.LocalDate;
import java.util.UUID;

/**
 * 系统文件工具类
 *
 * @author lvlinguang
 * @date 2021-02-28 12:30
 */
@Component
public class SysFileUtils {

    /**
     * 文件服务器中的目录分隔符
     */
    public static final String SEPRETOR = "/";

    @Autowired
    private MinioUtils minioUtils;

    /**
     * 文件上传
     *
     * @param object     文件对你
     * @param bucketName bucket名称
     * @return
     */
    @SneakyThrows
    public MinioObject uploadFile(MultipartFile object, String bucketName) {
        return this.uploadFile(object.getInputStream(), bucketName, object.getOriginalFilename());
    }

    /**
     * 文件上传
     *
     * @param object     文件对你
     * @param bucketName bucket名称
     * @param fileName   文件名
     * @return
     */
    @SneakyThrows
    public MinioObject uploadFile(MultipartFile object, String bucketName, String fileName) {
        return this.uploadFile(object.getInputStream(), bucketName, fileName);
    }

    /**
     * 文件上传
     *
     * @param object         文件对你
     * @param bucketName     bucket名称
     * @param randomFileName 文件名是否随机(是:按年/月/日/随机值储存,否:按原文件名储存)
     * @return
     */
    @SneakyThrows
    public MinioObject uploadFile(MultipartFile object, String bucketName, Boolean randomFileName) {
        //文件名
        String fileName = object.getOriginalFilename();
        if (randomFileName) {
            //扩展名
            String extName = FileUtil.extName(object.getOriginalFilename());
            if (StrUtil.isNotBlank(extName)) {
                extName = StrUtil.DOT + extName;
            }
            //新文件名
            fileName = randomFileName(extName);
        }
        return this.uploadFile(object.getInputStream(), bucketName, fileName);
    }

    /**
     * 文件上传
     *
     * @param object     文件对你
     * @param bucketName bucket名称
     * @param fileName   文件名
     * @return
     */
    @SneakyThrows
    public MinioObject uploadFile(InputStream object, String bucketName, String fileName) {
        try {
            minioUtils.uploadFile(bucketName, fileName, object);
            return new MinioObject(minioUtils.getFileInfo(bucketName, fileName));
        } catch (Exception e) {
            throw new Exception(e);
        } finally {
            if (object != null) {
                object.close();
            }
        }
    }

    /**
     * 下载文件
     *
     * @param response response
     * @param url      文件地址(/bucketName/fileName)
     */
    public void downloadFile(HttpServletResponse response, String url) {
        final String bucketName = getBucketName(url);
        final String filePath = getFilePath(url);
        this.downloadFile(response, bucketName, filePath);
    }

    /**
     * 下载文件
     *
     * @param response response
     * @param bucket   bucket名称
     * @param fileName 文件名
     */
    public void downloadFile(HttpServletResponse response, String bucket, String fileName) {
        try (InputStream inputStream = minioUtils.getFile(bucket, fileName)) {
            if ("jpg".equals(FileUtil.extName(fileName))) {
                response.setContentType("image/jpeg");
            } else if ("png".equals(FileUtil.extName(fileName))) {
                response.setContentType("image/png");
            } else {
                response.setContentType("application/octet-stream; charset=UTF-8");
            }
            IoUtil.copy(inputStream, response.getOutputStream());
        } catch (Exception e) {
            e.printStackTrace();
            response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
        }
    }

    /**
     * 获取链接地址的 文件名
     *
     * @param bucketFileUrl
     * @return
     */
    public static String getFilePath(String bucketFileUrl) {
        if (bucketFileUrl == null) {
            return null;
        }
        //去掉第一个分割符
        if (bucketFileUrl.startsWith(SEPRETOR)) {
            bucketFileUrl = bucketFileUrl.substring(1);
        }
        return bucketFileUrl.substring(bucketFileUrl.indexOf(SEPRETOR) + 1);
    }


    /**
     * 获取链接地址的 bucketName
     *
     * @param bucketFileUrl 地址(/{bucketName}/{path}/{fileName})
     * @return
     */
    public static String getBucketName(String bucketFileUrl) {
        if (bucketFileUrl == null) {
            return null;
        }
        //去掉第一个分割符
        if (bucketFileUrl.startsWith(SEPRETOR)) {
            bucketFileUrl = bucketFileUrl.substring(1);
        }
        return bucketFileUrl.substring(0, bucketFileUrl.indexOf(SEPRETOR));
    }

    /**
     * 生成新的文件名
     *
     * @param extName 扩展名
     * @return
     */
    public static String randomFileName(String extName) {
        LocalDate now = LocalDate.now();
        return now.getYear() + SEPRETOR +
                getFullNumber(now.getMonthValue()) + SEPRETOR +
                getFullNumber(now.getDayOfMonth()) + SEPRETOR +
                UUID.randomUUID().toString().replace("-", "") + extName;
    }

    /**
     * 得到数字全称,带0
     *
     * @param number
     * @return
     */
    public static String getFullNumber(Integer number) {
        if (number < 10) {
            return "0" + number;
        }
        return number.toString();
    }
}
View Code

6.相关实体类

package cn.cjq.entity;

import io.minio.messages.Item;
import io.minio.messages.Owner;
import lombok.AllArgsConstructor;
import lombok.Data;

import java.util.Date;

/**
 * @author Kartist
 */
@Data
@AllArgsConstructor
public class MinioItem {

    private String objectName;
    private Date lastModified;
    private String etag;
    private Long size;
    private String storageClass;
    private Owner owner;
    private String type;

    public MinioItem(Item item) {
        this.objectName = item.objectName();
        this.lastModified = item.lastModified();
        this.etag = item.etag();
        this.size = (long) item.size();
        this.storageClass = item.storageClass();
        this.owner = item.owner();
        this.type = item.isDir() ? "directory" : "file";
    }
}
View Code
package cn.cjq.entity;

import io.minio.ObjectStat;
import lombok.Data;

import java.util.Date;
@Data
public class MinioObject {
    private String bucketName;
    private String name;
    private Date createdTime;
    private Long length;
    private String etag;
    private String contentType;

    public MinioObject(ObjectStat os) {
        this.bucketName = os.bucketName();
        this.name = os.name();
        this.createdTime = os.createdTime();
        this.length = os.length();
        this.etag = os.etag();
        this.contentType = os.contentType();
    }
}
View Code

7.contrller入口

package cn.cjq.controller;


import cn.cjq.entity.MinioObject;
import cn.cjq.util.SysFileUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

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


@RestController
@RequestMapping("/hello")
@Slf4j
public class HelloWorldController {

    @Autowired
    private SysFileUtils sysFileUtils;

    /**
     * minio文件上传
     *
     * @param file
     * @param bucketName
     * @return
     */
    @PostMapping("/upload")
    public MinioObject upload(@RequestPart("file") MultipartFile file, @RequestParam("bucketName") String bucketName) {
        final MinioObject minioObject = sysFileUtils.uploadFile(file, bucketName, true);
        return minioObject;
    }

    /**
     * minio文件下载
     *
     * @return
     */
    @GetMapping("/info/**")
    public void getFile(HttpServletRequest request, HttpServletResponse response) {
        final String uri = request.getRequestURI();
        String fullName = uri.replace("/hello/info", "");
        sysFileUtils.downloadFile(response, fullName);
    }
}

8.post测试minio文件上传

192.168.1.114:8080/hello/upload

8.浏览器下载图片

url+bucketName+name:

http://192.168.1.114:8080/hello/info/cjq/2022/01/11/1106ab4078b2496699f93c0af971c737.png

 

参考文献:

https://www.cnblogs.com/lvlinguang/p/15774612.html
https://www.cnblogs.com/ssgeek/p/11072053.html
https://www.jianshu.com/p/f39e7255805b

 

标签:初体验,minio,oss,param,bucketName,import,public,String
来源: https://www.cnblogs.com/1234cjq/p/15787364.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有