minio 分布式对象存储

分布式文件系统应用

1.1、Minlo 介绍

Minlo 是一个基于Apache License v2.0开源协议的对象存储服务。它兼容亚马逊S3云存储服务接口,非常适合于存储大容量非结构化的数据,例如图片、视频、日志文件、备份数据和容器/虚拟机镜像等,而一个对象文件可以是任意大小,从几 kb到最大5T不等。
MinIo是一个非常轻量的服务,可以很简单的和其他应用的结合,类似 NodeJS, Redis 或者 MySQL。
官网: https://min.io/ http://www.minio.org.cn/

对象存储服务 (Obiect Storage Servie,OSS) 是一种海量、安全、低成本、高可靠的云存储服务,适合存放任意类型的文件。容量和处理能力弹性扩展,多种存储类型供选择,全面优化存储成本。

对于中小型企业,如果不选择存诸上云,那么 Minio 是个不错的选择,麻雀虽小,五脏俱全。当然 Minio 除了直接作为对象存储使用,还可以作为云上对象存储服务的网关层,无缝对接到 Amazon S3、MicroSoft Azure。
在中国: 阿里巴巴、腾讯、百度、中国联通、华为、中国移动等等9000多家企业也都在使用MinlO产品。

Docker 部署minio

1. 拉取minio镜像
docker pull minio/minio
2. 打包并运行容器
docker run -p 9000:9000 -p 9090:9090 --name minio -d --restart=always -e "MINIO_ACCESS_KEY=admin" -e "MINIO_SECRET_KEY=admin123456" -v /usr/docker/minio/data:/data -v /usr/docker/minio/config:/root/.minio minio/minio  server /data --console-address ":9090" -address ":9000"
#解释 9090 端口是控制台端口,9000是api接口
# 账号:MINIO_ACCESS_KEY=admin
# 密码:MINIO_SECRET_KEY=admin123456
# -v 文件映射 宿主机路径 /usr/docker/minio/data 映射到 docker容器的/data
# 宿主机路径/usr/docker/minio/config  映射到 docker容器的 /root/.minio minio/minio
# --address ":9000" minio 对外提供服务的api端口
# --console-address ":9090" minio后台管理端的端口

http://ip:9090/login
在这里插入图片描述
账号: admin 密码:admin123456

创建一个bucket 桶,命名为: mybucket

在这里插入图片描述

创建一个用户,为了生成 accessKey  和 secretKey 
选项都打上对钩

在这里插入图片描述

整合 springboot 上传下载

        <!--minio-->
        <dependency>
            <groupId>io.minio</groupId>
            <artifactId>minio</artifactId>
            <version>8.2.0</version>
        </dependency>
import io.minio.MinioClient;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class MinioConfig {

    // #对象存储服务的URL
    public static  String url = "http://ip:9000";
    // #账户
    public  static  String accessKey = "root";
    // #密码
    public  static String secretKey = "root123456";;

    // #桶名称
    public  static String bucketName = "mybucket";;


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

}
import io.minio.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.UUID;

@Component
public class MinioUtil {
    @Autowired
    private MinioClient minioClient;
    /**
     * 捅名称
     */
    private String bucketName = MinioConfig.bucketName;

    /**
     * putObject上传文件
     *
     * @param file 文件
     * @return filePath
     */
    public String putObject(MultipartFile file) throws Exception{
        //文件名
        String originalFilename = null;
        //文件流
        InputStream inputStream = null;
        Long size = null;
        String filePath = null;
        try {
            originalFilename = file.getOriginalFilename();
            inputStream = file.getInputStream();
            //文件大小
            size = file.getSize();
            //文件路径
            filePath = createFilePath(originalFilename);
            System.out.println(filePath+"\t文件路径");
            //存储方法 putObject
            minioClient.putObject(PutObjectArgs.builder()
                    .bucket(bucketName)
                    .object(filePath)
                    .stream(inputStream, size, -1)
                    .contentType(file.getContentType())
                    .build());
        }finally {
            inputStream.close();
        }
        return filePath;
    }


    /**
     * 下载文件
     *
     * @param filePath 文件路径
     */
    public void getObject(HttpServletResponse httpServletResponse, String filePath) throws  Exception {
        String fileName = getFileName(filePath);
        InputStream inputStream = minioClient.getObject(GetObjectArgs.builder()
                .bucket(bucketName)
                .object(filePath)
                .build());
        downloadFile(httpServletResponse, inputStream, fileName);
    }

    /**
     * 获取文件路径
     *
     * @param originalFilename 原始文件名称
     * @return FilePath
     */
    public String createFilePath(String originalFilename) {
       // 获取文件名后缀 ,如果没有后缀就获取全文件名
        int dotIndex = originalFilename.lastIndexOf(".");
        String fileExtension = "";
        if (dotIndex != -1) {
            fileExtension = UUID.randomUUID().toString().replace("-","")+"."+originalFilename.substring(dotIndex + 1);
        } else {
            fileExtension = originalFilename;
        }
        return new SimpleDateFormat("yyyy/MM/dd").format(new Date()) + "/" + fileExtension;
    }

    /**
     * 根据文件路径获取文件名称
     *
     * @param filePath 文件路径
     * @return 文件名
     */
    public String getFileName(String filePath) {
        String[] split = StringUtils.split(filePath, "/");
        return split[split.length - 1];
    }

    /**
     * 下载文件
     *
     * @param httpServletResponse httpServletResponse
     * @param inputStream         inputStream
     * @param fileName            文件名
     * @throws IOException IOException
     */
    public void downloadFile(HttpServletResponse httpServletResponse, InputStream inputStream, String fileName) throws IOException {
        //设置响应头信息,告诉前端浏览器下载文件
        httpServletResponse.setContentType("application/octet-stream;charset=UTF-8");
        httpServletResponse.setCharacterEncoding("UTF-8");
        httpServletResponse.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
        //获取输出流进行写入数据
        OutputStream outputStream = httpServletResponse.getOutputStream();
        // 将输入流复制到输出流
        byte[] buffer = new byte[4096];
        int bytesRead = -1;
        while ((bytesRead = inputStream.read(buffer)) != -1) {
            outputStream.write(buffer, 0, bytesRead);
        }
        // 关闭流资源
        inputStream.close();
        outputStream.close();
    }

}

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;

@RestController
@RequestMapping(value = "/file")
public class FileController {

    @Autowired
    MinioUtil minioUtil;

    @PostMapping("/upload")
    public String upload(@RequestPart MultipartFile file) {
        String filePath;
        try {
            filePath = minioUtil.putObject(file);
        } catch (Exception e) {
            e.printStackTrace();
            return ("上传失败");
        }
        return filePath;
    }

    @GetMapping("/download")
    public void download(HttpServletResponse response, @RequestParam(value = "filepath") String filepath)  {
        try {
            minioUtil.getObject(response, filepath);
        } catch (Exception e) {
           response.setStatus(500);
            e.printStackTrace();
        }
    }

}

测试,上传可以返回路径,桶内也有上传文件
在这里插入图片描述

nginx 指向静态文件夹,不预览,输入文件名全路径直接下载(docker 映射的文件存储位置),文件夹赋予 777 权限

在这里插入图片描述

在这里插入图片描述

kkfileview 可以查看

在这里插入图片描述
在这里插入图片描述

<!DOCTYPE html>
<html>
    <head>
        <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/js-base64@3.7.2/base64.min.js"></script>
    </head>
 
    <script>
        var url = 'http://服务器IP/down/2023/12/22/ea5ed092c5be423da86ea5e5e5e6c2f4.html'; //文件地址
        window.open('http://127.0.0.1:8012/onlinePreview?url='+encodeURIComponent(Base64.encode(url)));
    </script>
</html>

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/263294.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

LVM将多个磁盘组成一个逻辑卷实战

LVM&#xff08;Logical Volume Manager&#xff09;是一种逻辑卷管理器&#xff0c;是Linux系统中的一个重要的存储管理技术。它的主要作用是将若干个硬盘分区或者物理硬盘合并成一个逻辑卷组&#xff08;Volume Group&#xff0c;简称VG&#xff09;&#xff0c;然后再将逻辑…

使用Flask逐步搭建Web应用程序

大家好&#xff0c;Flask是一个使用Python编写的轻量级Web应用框架。它被设计成简单、易于学习和使用的&#xff0c;同时具备足够的灵活性和扩展性&#xff0c;以满足各种规模的Web应用开发需求。本文我们将介绍一个使用Flask逐步搭建Web应用程序的简单入门示例。 1.安装Flask…

开发模型和测试模型

1. 开发模型 1.1 瀑布模型 瀑布模型是其他模型的基础框架 start—>需求分析---->计划----->设计----->编码----->测试----->End&#xff08;其实就是软件开发的生命周期&#xff09; 特点&#xff1a;线性的开发流程 缺陷&#xff1a;测试被后置。①风险往…

企业“数据入表”之政策及业务模式解读

2023年8月21日&#xff0c;财政部重磅发布了《企业数据资源相关会计处理暂行规定》&#xff08;以下简称“暂行规定”&#xff09;&#xff0c;该规定将于2024年1月1日正式施行。 “暂行规定”发布后&#xff0c;引起全社会的广泛关注&#xff0c;关注的焦点集中在数据入表概念…

指标体系构建-01-什么是数据指标

参考 四千字全面解析数据产品经理必知概念&#xff1a;标签、维度、指标 什么是数据指标 指标是指于其中打算达到的指数&#xff0c;规格&#xff0c;标准等,是用数据对事物进行描述的工具。通常指标对应是否有价值取决于这个指标的实际意义。同时关注指标对应的数值&#x…

Leetcode 134 加油站

题意理解&#xff1a; 给定n个站点&#xff0c;两个数组gas表达每个站点可加的油量&#xff0c;cost表达到下一站点所需耗费的油量。 gas [1,2,3,4,5], cost [3,4,5,1,2] 要求从下表为i的站点开始&#xff0c;刚好能支撑汽车在每个站点转一圈后回到出发位置。 解题思路&#…

天锐绿盾加密系统是做什么用的?——防止公司内部核心文件数据 \ 资料外泄

天锐绿盾加密系统是一款专业的数据加密软件&#xff0c;主要用于保护企业数据的安全性和完整性。该系统采用先进的加密技术&#xff0c;对数据进行加密处理&#xff0c;确保数据在传输和存储过程中的安全性。 PC访问地址&#xff1a;www.drhchina.com 天锐绿盾加密系统的主要…

RocketMQ系统性学习-RocketMQ高级特性之消息存储在Broker的文件布局

&#x1f308;&#x1f308;&#x1f308;&#x1f308;&#x1f308;&#x1f308;&#x1f308;&#x1f308; 【11来了】文章导读地址&#xff1a;点击查看文章导读&#xff01; &#x1f341;&#x1f341;&#x1f341;&#x1f341;&#x1f341;&#x1f341;&#x1f3…

【C语言】自定义类型:结构体深入解析(二)结构体内存对齐宏offsetof计算偏移量结构体传参

文章目录 &#x1f4dd;前言&#x1f320; 结构体内存对齐&#x1f309;内存对齐包含结构体的计算&#x1f320;宏offsetof计算偏移量&#x1f309;为什么存在内存对⻬?&#x1f320; 结构体传参&#x1f6a9;总结 &#x1f4dd;前言 本小节&#xff0c;我们学习结构的内存对…

Redis设计与实现之RDB

目录 一、RDB 1、保存 2、 SAVE 、BGSAVE 、AOF 写入和 BGREWRITEAOF SAVE BGSAVE 3、载入 4、RDB 文件结构 REDIS DB-DATA SELECT-DB KEY-VALUE-PAIRS EOF CHECK-SUM 二、 小结 一、RDB 在运行情况下&#xff0c;Redis 以数据结构的形式将数据维持在内存中&…

头歌—衍生密码体制

# 第1关&#xff1a;Rabin密码体制 题目描述 任务描述 Rabin密码体制是RSA密码体制的一种。 本关任务&#xff1a;使用Rabin密码体制对给定的明文进行加密。 相关知识 为了完成本关任务&#xff0c;你需要掌握&#xff1a;Rabin密码体制。 Rabin密码体制 在本关中&#x…

幻彩LED灯带芯片:SM16703SP单点单控 断点续传

幻彩LED灯带芯片SM16703SP3是一款单点单控断点续传的芯片&#xff0c;它采用了先进的技术&#xff0c;可以实现灯光的变化和控制。这款芯片不仅仅可以提供各种丰富多彩的灯光效果&#xff0c;还有断点续传功能&#xff0c; LED断点续传灯条采用了双信号线交叉传输的方案&#x…

【Spring Boot】面试题汇总,带答案的那种

继上次的文章【MySQL连环炮&#xff0c;你抗的住嘛&#xff1f;】爆火之后&#xff0c;越来越多的小伙伴后台留言&#xff0c;要求阿Q总结下其他的“连环炮”知识点&#xff0c;想在金九银十的面试黄金期轻松对线面试官。 同样为了节省大家的时间&#xff0c;阿Q最近对【Sprin…

链接未来:深入理解链表数据结构(二.c语言实现带头双向循环链表)

上篇文章简述讲解了链表的基本概念并且实现了无头单向不循环链表&#xff1a;链接未来&#xff1a;深入理解链表数据结构&#xff08;一.c语言实现无头单向非循环链表&#xff09;-CSDN博客 那今天接着给大家带来带头双向循环链表的实现&#xff1a; 文章目录 一.项目文件规划…

在线商城系统软件源码与报价_OctShop

随着互联网、5G、人工智能的快速发展&#xff0c;人们在家购物已经是生活的重要方式。各种在线商城系统的不断涌现&#xff0c;同时&#xff0c;也给传统的企业商家销售带来了不小的压力&#xff0c;那么&#xff0c;如何调整&#xff0c;以适应时代的发展呢&#xff1f;经过不…

【数据结构和算法】最大连续1的个数 III

其他系列文章导航 Java基础合集数据结构与算法合集 设计模式合集 多线程合集 分布式合集 ES合集 文章目录 其他系列文章导航 文章目录 前言 一、题目描述 二、题解 2.1 方法一&#xff1a;滑动窗口 2.2 滑动窗口解题模板 三、代码 3.1 方法一&#xff1a;滑动窗口 四、…

世界第一!移动云刷新虚拟化性能测试世界纪录

近日&#xff0c;国际权威性能测评机构SPEC公布了最新一期虚拟化性能基准测试结果&#xff0c;移动云大云天元操作系统&#xff08;BC-Linux&#xff09;&#xff0c;凭借其出色的虚拟化性能&#xff0c;一举将世界纪录提升了10%&#xff0c;总分达到了8336分。 移动云SPEC vir…

Mybatis-plus动态条件查询QueryWrapper的函数用法

目录 前言1. QueryWrapper2. 函数3. Demo 前言 原本都是在Mapper文件中修改&#xff0c;直到看到项目中使用了QueryWrapper这个函数&#xff0c;大致了解了用法以及功能&#xff0c;发现还可以&#xff01; 对此此贴为科普帖以及笔记帖 1. QueryWrapper MyBatis-Plus 是 My…

Angular 进阶之五: Signals到底用不用?

Angular 在V16的时候推出了Signals&#xff0c;在17正式作为主打功能之一强烈推荐&#xff0c;看过了各种博主的各种科普文章也没说明白&#xff0c;到底这东西值不值得用&#xff1f;毕竟项目大了&#xff0c;重构代码也不是闹着玩儿的。各种科普文章主要在说两点&#xff1a;…

pake协议传输文件magic-wormhole

pake协议传输文件magic-wormhole 1 magic-wormhole简介其他介绍 2 安装magic-wormhole3 使用示范发送文件指定虫洞码长度 接收文件 1 magic-wormhole简介 16.7k star 强推&#xff0c;丝滑、简洁、安全的开源工具——magic-wormhole 项目地址&#xff1a;https://github.com/…