MINIO简要使用说明

一、项目信息说明

minio Server版本: linux-amd64/minio 与 windows-amd64/minio.exe
minio Client版本: linux-amd64/mc 与 windows-amd64/mc.exe
minio sdk: https://dl.min.io/sdk/minio-java/

官方文档: MinIO Client (mc) — MinIO祼机使用文档

MinIO Server — MinIO祼机使用文档

二、使用说明

1.使用体验

单机部署简单,使用一条指令即可启动、配置服务器节点(服务器地址,端口、api端口)minio服务,自带页面。
mc客户端有详细中文文档,api调用接口简易

支持生命周期管理(支持日期与天数、支持设置桶内文件夹),设置后,文件会根据规则自动删除源文件

2.大体工作流程

minioServer部署—>mc客户端/api接口创建 存储桶 ---->mc客户端/api接口配置生命周期规则—>minio页面/api接口存储文件—>minio页面/api接口获取文件或文件url

三、minio Server部署

1.启动服务

linux:

./minio server /data/minio  --address ip:api调用端口  --console-address ip:服务器端口 --config-dir 配置文件地址

window:

.\minio.exe server D:\Utils\minio\  --address ip:api调用端口  --console-address ip:服务器端口 --config-dir 配置文件地址

minIO server在默认情况下会将所有配置信息存到 ${HOME}/.minio/config.json 文件中。 可用--config-dir在启动服务时重写

# 设置用户名
set MINIO_ACCESS_KEY=minioadmin
# 设置密码(8位)
set MINIO_SECRET_KEY=minioadmin
3.证书目录

TLS证书存在${HOME}/.minio/certs目录下,你需要将证书放在该目录下来启用HTTPS 。如果你是一个乐学上进的好青年,这里有一本免费的秘籍传授一你: 如何使用TLS安全的访问minio.

以下是一个带来TLS证书的MinIO server的目录结构。

Copy$ tree ~/.minio
/home/user1/.minio
├── certs
│   ├── CAs
│   ├── private.key
│   └── public.crt
└── config.json

四、MinIO Client使用

MinIO Client 简称mc,是minio服务器的客户端,对ls,cat,cp,mirror,diff,find等UNIX命令提供了一种替代方案,它支持文件系统和兼容Amazon S3的云存储服务(AWS Signature v2和v4)。

1.mc指令

ls 列出文件和文件夹。
mb 创建一个存储桶或一个文件夹。
cat 显示文件和对象内容。
pipe 将一个STDIN重定向到一个对象或者文件或者STDOUT。
share 生成用于共享的URL。
cp 拷贝文件和对象。
mirror 给存储桶和文件夹做镜像。
find 基于参数查找文件。
diff 对两个文件夹或者存储桶比较差异。
rm 删除文件和对象。
events 管理对象通知。
watch 监听文件和对象的事件。
policy 管理访问策略。
session 为cp命令管理保存的会话。
config 管理mc配置文件。
update 检查软件更新。
version 输出版本信息。

2.常用命令
//设置        别名  api地址	用户名      密码
mc alias set ALIAS HOSTNAME ACCESSKEY SECRETKEY 
//列出指定桶的当前生命周期管理规则
mc ilm list TARGET [FLAGS]
//添加新的存储桶生命周期管理规则
mc ilm add TARGET [FLAGS]
// 使用 mc ilm add 和 --expiry-days 到 在对象创建数天后使存储桶内容过期:
mc ilm add ALIAS/PATH --expiry-days "DAYS"
//使用 mc ilm remove 删除存储桶生命周期管理规则 
mc ilm remove --id "RULE" ALIAS/PATH

五、MINIO SDK(Java) Java Client API参考文档 | Minio中文文档

<!--maven-->
            <dependency>
                <groupId>io.minio</groupId>
                <artifactId>minio</artifactId>
                <version>8.4.1</version>
                <exclusions>
                    <exclusion>
                        <groupId>com.squareup.okhttp3</groupId>
                        <artifactId>okhttp</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
<!--minio的okhttp有可能会报错-->
            <dependency>
                <groupId>com.squareup.okhttp3</groupId>
                <artifactId>okhttp</artifactId>
                <version>4.9.0</version>
            </dependency>
        </dependencies>
<!--gradle-->
dependencies {
    compile 'io.minio:minio:8.4.1'
#minio
minio:
  url: http://10.10.18.178:9000
  accessKey: minioadmin
  secretKey: minioadmin
  bucketName: bucket-test01
  #分区上传文件大小
  partSize: 104857600
import cn.akeparking.middleware.service.minio.MinioTemplate;
import io.minio.MinioClient;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
 * @author qiukl
 * @create 2022/5/24 17:51
@Data
@Configuration
@ConfigurationProperties(prefix = "minio")
public class MinIoConfig {
     * 服务地址(服务接口地址)
    private String url;
     * 用户名
    private String accessKey;
    private String secretKey;
     * 存储桶名称
    private String bucketName;
    private Integer partSize;
    @Bean
    public MinioTemplate getMinioClient() {
        return new MinioTemplate(url,accessKey, secretKey,partSize);
3.常用api
1)创建储存桶

通过MinioTemplate.createBucket(bucketName)创建桶,或调用sdk包的minioClient.makeBucket方法

2)设置生命周期

通过MinioTemplate.setBucketExpirationByDays(bucketName,prefix,days,ruleName)创建对应桶的生命周期,prefix对应相应的文件夹,days对应过期天数,ruleName对应文件名称

3)存入文件

通过MinioTemplate.putObject(bucketName,objectName,base64Str/MultipartFile/InputStream)存入文件,实际上皆转为上传

PutObjectArgs putObjectArgs = PutObjectArgs.builder()
        .bucket(bucketName)
        .object(objectName)
        .stream(stream, size, partSize)
        .build();
client.putObject(putObjectArgs);

4)取文件

通过MinioTemplate.getObject(bucketName,objectName)获取对应的文件流,或者通过MinioTemplate.presignedObjectUrl(bucketName,objectName,时间, 时间单位)来获取有期限的文件url

4.工具类
import io.minio.*;
import io.minio.http.Method;
import io.minio.messages.*;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.multipart.MultipartFile;
import sun.misc.BASE64Decoder;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.time.ZonedDateTime;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.TimeUnit;
 * @author qiukl
 * @create 2022/5/24 17:40
@AllArgsConstructor
@Slf4j
public class MinioTemplate {
    private String endpoint;
    private String accessKey;
    private String secretKey;
    private int partSize;
    private MinioClient client;
    @SneakyThrows
    public MinioTemplate(String endpoint, String accessKey, String secretKey, int partSize) {
        this.endpoint = endpoint;
        this.accessKey = accessKey;
        this.secretKey = secretKey;
        this.partSize = partSize;
        this.client = MinioClient.builder()
                .endpoint(endpoint)
                .credentials(accessKey, secretKey)
                .build();
     * 创建bucket
     * @param bucketName bucket名称
    public void createBucket(String bucketName) throws Exception {
        if (!client.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())) {
            client.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
     * @param bucketName
     * @param days
     * @param ruleName
     * @throws Exception
    public void setBucketExpirationByDays(String bucketName,String prefix,Integer days,String ruleName) throws Exception{
        // 获取配置
        LifecycleConfiguration lifecycleConfiguration =
                client.getBucketLifecycle(
                        GetBucketLifecycleArgs
                                .builder()
                                .bucket(bucketName)
                                .build());
        List<LifecycleRule> rules = lifecycleConfiguration.rules();
        List<LifecycleRule> rulesNew = new ArrayList<>();
        rulesNew.addAll(rules);
        // 配置生命周期规则
        rulesNew.add(
                new LifecycleRule(
                        Status.ENABLED, // 开启状态
                        null,
                        new Expiration((ZonedDateTime) null, days, null), // 保存365天
                        new RuleFilter(prefix), // 目录配置
                        ruleName,
                        null,
                        null,
                        null)
        LifecycleConfiguration lifecycleConfigurationNew = new LifecycleConfiguration(rulesNew);
        // 添加生命周期配置
        client.setBucketLifecycle(
                SetBucketLifecycleArgs
                        .builder()
                        .bucket(bucketName)
                        .config(lifecycleConfigurationNew)
                        .build()
    public List<LifecycleRule> getBucketLifecycleRule(String bucketName) throws Exception{
        // 获取配置
        LifecycleConfiguration lifecycleConfiguration1111 =
                client.getBucketLifecycle(
                        GetBucketLifecycleArgs
                                .builder()
                                .bucket(bucketName)
                                .build());
        List<LifecycleRule> rules1 = lifecycleConfiguration1111.rules();
        for (LifecycleRule lifecycleRule:rules1) {
            log.debug(lifecycleRule.toString());
            log.debug("Lifecycle status is " + lifecycleRule.status()
                    +"\nLifecycle prefix is " + lifecycleRule.filter().prefix()
                    +"\nLifecycle expiration days is " + lifecycleRule.expiration().days());
        return rules1;
     * 获取全部bucket
     * https://docs.minio.io/cn/java-client-api-reference.html#listBuckets
    public List<Bucket> getAllBuckets() throws Exception {
        return client.listBuckets();
     * 根据bucketName获取信息
     * @param bucketName bucket名称
    public Optional<Bucket> getBucket(String bucketName) throws Exception {
        return client.listBuckets().stream().filter(b -> b.name().equals(bucketName)).findFirst();
     * 根据bucketName删除信息
     * @param bucketName bucket名称
    public void removeBucket(String bucketName) throws Exception {
        client.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());
     * 分区上传文件
     * @param bucketName bucket名称
     * @param objectName 文件名称
     * @param stream 文件流
     * @param size 文件大小
    public String putObject(String bucketName, String objectName, InputStream stream, Long size) throws Exception{
        PutObjectArgs putObjectArgs = PutObjectArgs.builder()
                .bucket(bucketName)
                .object(objectName)
                .stream(stream, size, partSize)
                .build();
        ObjectWriteResponse objectWriteResponse = client.putObject(putObjectArgs);
        return objectWriteResponse.object();
     * 根据文件前置查询文件
     * @param bucketName bucket名称
     * @param prefix     前缀
     * @param recursive  是否递归查询
     * @return MinioItem 列表
    public List<Item> getAllObjectsByPrefix(String bucketName, String prefix, boolean recursive) throws Exception {
        List<Item> objectList = new ArrayList<>();
        ListObjectsArgs listObjectsArgs = ListObjectsArgs.builder()
                .bucket(bucketName)
                .prefix(prefix)
                .recursive(recursive)
                .build();
        Iterable<Result<Item>> objectsIterator = client
                .listObjects(listObjectsArgs);
        while (objectsIterator.iterator().hasNext()) {
            objectList.add(objectsIterator.iterator().next().get());
        return objectList;
     * 获取文件外链
     * 这里的 method 方法决定最后链接是什么请求获得
     *  expiry 决定这个链接多久失效
     * @param bucketName bucket名称
     * @param objectName 文件名称
     * @param duration 有效大小
     * @param
     * @return url
    public String getObjectURL(String bucketName, String objectName,Integer duration, TimeUnit unit) throws Exception {
        if (null==duration||null==unit){
            duration = 7;
            unit = TimeUnit.DAYS;
        GetPresignedObjectUrlArgs args = GetPresignedObjectUrlArgs.builder()
                .bucket(bucketName)
                .method(Method.GET)
                .expiry(duration, unit)
                .object(objectName)
                .build();
        return client.getPresignedObjectUrl(args);
     * 获取文件
     * @param bucketName bucket名称
     * @param objectName 文件名称
     * @return 二进制流
    public InputStream getObject(String bucketName, String objectName) throws Exception {
        GetObjectArgs getObjectArgs = GetObjectArgs.builder()
                .bucket(bucketName)
                .object(objectName)
                .build();
        return client.getObject(getObjectArgs);
     * 上传文件 base64
     * @param bucketName bucket名称
     * @param objectName 文件名称
     * @param base64Str 文件base64
    public String putObject(String bucketName, String objectName, String base64Str) throws Exception{
        InputStream inputStream = new ByteArrayInputStream(base64Str.getBytes());
        // 进行解码
        BASE64Decoder base64Decoder = new BASE64Decoder();
        byte[] byt = new byte[0];
        try {
            byt = base64Decoder.decodeBuffer(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        inputStream = new ByteArrayInputStream(byt);
        putObject(bucketName, objectName, inputStream, Long.valueOf(byt.length));
        return objectName;
     * 上传文件
     * @param bucketName bucket名称
     * @param objectName 文件名称
     * @param file 文件
     * @throws Exception
    public String putObject( String bucketName,String objectName, MultipartFile file) throws Exception{
        this.putObject(bucketName, objectName, file.getInputStream(), file.getSize());
        return objectName;
     * 获取文件信息
     * @param bucketName bucket名称
     * @param objectName 文件名称
     * @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#statObject
    public StatObjectResponse getObjectInfo(String bucketName, String objectName) throws Exception {
        StatObjectArgs statObjectArgs = StatObjectArgs.builder()
                .bucket(bucketName)
                .object(objectName)
                .build();
        return client.statObject(statObjectArgs);
     * 删除文件
     * @param bucketName bucket名称
     * @param objectName 文件名称
     * @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#removeObject
    public void removeObject(String bucketName, String objectName) throws Exception {
        RemoveObjectArgs removeObjectArgs = RemoveObjectArgs.builder()
                .bucket(bucketName)
                .object(objectName)
                .build();
        client.removeObject(removeObjectArgs);
     * 根据文件名返回对应contentType
     * @param objectName
     * @return
    private String getContentType(String objectName) {
        //if(FileNameUtil.isPicture(objectName)) {
        //    return "image/jpeg";
        //if(FileNameUtil.isVideo(objectName)) {
        //    return "video/mp4";
        return null;
     * 获取直传链接
     * @param bucketName bucket名称
     * @param objectName 文件名称
     * @throws Exception
    public String presignedPutObject( String bucketName,String objectName) throws Exception{
        GetPresignedObjectUrlArgs getPresignedObjectUrlArgs = GetPresignedObjectUrlArgs.builder()
                .method(Method.PUT)
                .bucket(bucketName)
                .object(objectName)
                .expiry(7, TimeUnit.DAYS)
                .build();
        return client.getPresignedObjectUrl(getPresignedObjectUrlArgs);
     * 合并文件
     * @param bucketName
     * @param chunkNames
     * @param targetObjectName
     * @return
     * @throws Exception
    public String composeObject(String bucketName, List<String> chunkNames, String targetObjectName) throws Exception{
        List<ComposeSource> sources = new ArrayList<>(chunkNames.size());
        for (String chunkName : chunkNames) {
            ComposeSource composeSource = ComposeSource.builder()
                    .bucket(bucketName)
                    .object(chunkName)
                    .build();
            sources.add(composeSource);
        ComposeObjectArgs composeObjectArgs = ComposeObjectArgs.builder()
                .bucket(bucketName)
                .sources(sources)
                .object(targetObjectName)
                .build();
        ObjectWriteResponse objectWriteResponse = client.composeObject(composeObjectArgs);
        return objectWriteResponse.object();
				
MinIO Java Client SDK提供简单的API来访问任何与Amazon S3兼容的对象存储服务。官方demo: https://github.com/minio/minio-java 官方文档:https://docs.min.io/docs/java-client-api-reference.html 新版 MinIO和旧版在 API使用上还是有一定的区别,比如:新版 MinIO采用 Builder构建者模式来构造 MinioClient对象。所以,官方demo仅供参考,尽量查看英文官方文档。
minio基础知识介绍 文章目录minio基础知识介绍1 概述1.1 特性1.2 部署运行模式2 存储机制2.1 纠错码2.2 RS code编码数据恢复原理2.3 校验和3 minio多租户和多用户3.1 多租户3.2 多用户4 minio集群及扩容4.1 minio集群架构4.2 minio集群的数据对象存储4.3 MinIO集群扩容方式5 总结 minio为开源的高可用分部署对象存储服务组件,已经提供了分布式部署的解决方案,实现高可靠、高可用的资源存储,MinIO以极简主义为指导进行设计,追求极致的
npm install --save hexo-deployer-oss-aliyun # https://oss.console.aliyun.com/bucket/oss-us-west-1/f9a329b03 deploy : type : aliyun-oss region : <Region> # oss-us-west-1 bucket : <Bucket> # f9a329b03 accessKeyId : <Aliyun> accessKeySecret : <Aliyun> hexo d
官方的git代码库,给的example是5.x版本案例,并且官方使用npm run build-dist打不了包,可能代码太过来老旧; 案例中OSS.wrapper属于6.x以下版本,已改为OSS方式,采用实际子账户进行分片上传,发现没有问题; 操作步骤: 1,npm install 2,cd example 3,npm install 4,npm run server 5,npm run dev 别忘记配置example/server/config.js的accessId和accessKey以及其他,配置完成后即可使用,跨域问题,可以使用谷歌浏览器,去除跨域限制即可; 打包方式,在根目录运行: npm run build-dist 会在dist文件夹下面生成两个文件,压缩的和未压缩的
根据官方定义: MinIO 是在 Apache License v2.0 下发布的对象存储服务器。 它与 Amazon S3 云存储服务兼容。 它最适合存储非结构化数据,如照片,视频,日志文件,备份和容器/ VM 映像。 对象的大小可以从几 KB 到最大 5TB。 MinIO 服务器足够轻,可以与应用程序堆栈捆绑在一起,类似于 NodeJS,Redis 和 MySQL。...