CDN到期不想续费?!MINIO救个场!

news2025/2/25 12:15:22

一、安装MINIO

下载

wget https://dl.min.io/server/minio/release/linux-amd64/archive/minio-20230413030807.0.0.x86_64.rpm -O minio.rpm

安装

yum install minio.rpm

二、启动 MinIO 服务器

  • 创建启动实例目录
mkdir ~/minio
  • 启动 MInIO实例
minio server ~/minio --console-address :9090

启动成功界面截图如下:

启动成功后可以看到 MinIO 版本。 

 三、创建凭据密钥

  • 登录:http://localhost:9090

账号:minioadmin

密码:minioadmin

  • Create Bucket

创建桶示例截图如下:

  • 创建租户

创建租户示例截图如下:

  • 创建凭据密钥

首先点击用户,如下:

 接下来进入如下界面后,点击【Create Access Key】

 接下来进入如下界面后点击【Create】

 弹窗后,点击【Download for import】下载,如下 截图

下载后内容如下:

{"url":"http://127.0.0.1:9000","accessKey":"FZULfNYYF3LtrnOx","secretKey":"k3DPt92mF5D6GhfVgiQhOlDoNdXNBcng","api":"s3v4","path":"auto"}

 注意:url和登录时的端口不一样哦,接下来整合到Spring Boot中时要用到!

四、Spring Boot 整合 Minio

  • 添加依赖
        <dependency>
            <groupId>io.minio</groupId>
            <artifactId>minio</artifactId>
            <version>8.5.2</version>
        </dependency>
  • 在 application.properties 中添加 minio 密钥,如下:
################################## minio 配置 ##################################
spring.minio.url=http://127.0.0.1:9000
spring.minio.access-key=FZULfNYYF3LtrnOx
spring.minio.secret-key=k3DPt92mF5D6GhfVgiQhOlDoNdXNBcng
spring.minio.bucket-name=song
  • 创建读取配置类
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;

/**
 * minio配置读取
 *
 * @author songjianyong
 */
@Configuration
@ConfigurationProperties(prefix = "spring.minio")
@Data
public class MinioConfiguration {
    private String accessKey;
    private String secretKey;
    private String url;
    private String bucketName;

    @Bean
    public MinioClient minioClient() {
        return MinioClient.builder()
                .endpoint(url)
                .credentials(accessKey, secretKey)
                .build();
    }
}
  • 创建minio 服务接口及实现类

接口代码如下

import io.minio.http.Method;
import org.springframework.web.multipart.MultipartFile;

import java.time.ZonedDateTime;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * minio 服务接口
 *
 * @author songjianyong
 */
public interface IMinioService {
    /**
     * 获取上传临时签名
     *
     * @param fileName 文件名称
     * @param time     时间
     * @return {@link Map}
     */
    Map<String, String> getPolicy(String fileName, ZonedDateTime time);

    /**
     * 获取上传文件的url
     *
     * @param objectName 对象名称
     * @param method     方法
     * @param time       时间
     * @param timeUnit   时间单位
     * @return {@link String}
     */
    String getPolicyUrl(String objectName, Method method, int time, TimeUnit timeUnit);

    /**
     * 上传文件
     *
     * @param file     文件
     * @param fileName 文件名称
     */
    void upload(MultipartFile file, String fileName);

    /**
     * 根据filename获取文件访问地址
     *
     * @param objectName 对象名称
     * @param time       时间
     * @param timeUnit   时间单位
     * @return {@link String}
     */
    String getUrl(String objectName, int time, TimeUnit timeUnit);
}

接口实现如下

import com.coocaa.spider.imdb.config.MinioConfiguration;
import com.coocaa.spider.imdb.service.IMinioService;
import io.minio.GetPresignedObjectUrlArgs;
import io.minio.MinioClient;
import io.minio.PostPolicy;
import io.minio.PutObjectArgs;
import io.minio.errors.*;
import io.minio.http.Method;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.time.ZonedDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * minio服务
 *
 * @author songjianyong
 * @date 2023/04/18
 */
@Slf4j
@Service
public class MinioServiceImpl implements IMinioService {
    @Resource
    private MinioClient minioClient;

    @Resource
    private MinioConfiguration minioConfiguration;


    @Override
    public Map<String, String> getPolicy(String fileName, ZonedDateTime time) {
        PostPolicy postPolicy = new PostPolicy(minioConfiguration.getBucketName(), time);
        postPolicy.addEqualsCondition("key", fileName);
        try {
            Map<String, String> postFormData = minioClient.getPresignedPostFormData(postPolicy);
            HashMap<String, String> policyMap = new HashMap<>(8);
            postFormData.forEach((k, v) -> {
                policyMap.put(k.replaceAll("-", ""), v);
            });
            policyMap.put("host", minioConfiguration.getUrl() + "/" + minioConfiguration.getBucketName());
            return policyMap;
        } catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidKeyException | InvalidResponseException | IOException | NoSuchAlgorithmException | ServerException | XmlParserException e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }

    @Override
    public String getPolicyUrl(String objectName, Method method, int time, TimeUnit timeUnit) {
        try {
            return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
                    .method(method)
                    .bucket(minioConfiguration.getBucketName())
                    .object(objectName)
                    .expiry(time, timeUnit).build());
        } catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidKeyException | InvalidResponseException | IOException | NoSuchAlgorithmException | XmlParserException | ServerException e) {
            log.error(e.getMessage(), e);
        }
        return null;
    }


    @Override
    public void upload(MultipartFile file, String fileName) {
        // 使用putObject上传一个文件到存储桶中。
        try(InputStream inputStream = file.getInputStream()) {
            minioClient.putObject(PutObjectArgs.builder()
                    .bucket(minioConfiguration.getBucketName())
                    .object(fileName)
                    .stream(inputStream, file.getSize(), -1)
                    .contentType(file.getContentType())
                    .build());
        } catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidKeyException | InvalidResponseException | IOException | NoSuchAlgorithmException | ServerException | XmlParserException e) {
            log.error(e.getMessage(), e);
        }
    }

    @Override
    public String getUrl(String objectName, int time, TimeUnit timeUnit) {
        String url = null;
        try {
            url = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
                    .method(Method.GET)
                    .bucket(minioConfiguration.getBucketName())
                    .object(objectName)
                    .expiry(time, timeUnit).build());
        } catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidKeyException | InvalidResponseException | IOException | NoSuchAlgorithmException | XmlParserException | ServerException e) {
            log.error(e.getMessage(), e);
        }
        return url;
    }
}
  •  创建上传文件Controller类
import com.coocaa.spider.imdb.service.IMinioService;
import com.coocaa.spider.imdb.vo.ResponseVO;
import io.minio.http.Method;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.time.ZonedDateTime;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 上传文件控制器
 *
 * @author songjianyong
 * @date 2023/04/18
 */
@RestController
@RequestMapping("/minio")
@Validated
public class UploadController {

    @Resource
    private IMinioService minioService;

    @PostMapping("/upload")
    public ResponseVO<String> upload(@RequestParam("file") MultipartFile file, @RequestParam("fileName") String fileName) {
        minioService.upload(file, fileName);
        String url = minioService.getUrl(fileName, 7, TimeUnit.DAYS);
        return ResponseVO.buildSuccessResult(url);
    }

    @GetMapping("/policy")
    public ResponseVO<Map<String, String>> policy(@RequestParam("fileName") String fileName) {
        Map<String, String> policy = minioService.getPolicy(fileName, ZonedDateTime.now().plusMinutes(10));
        return ResponseVO.buildSuccessResult(policy);
    }

    @GetMapping("/uploadUrl")
    public ResponseVO<String> uploadUrl(@RequestParam("fileName") String fileName) {
        String url = minioService.getPolicyUrl(fileName, Method.PUT, 2, TimeUnit.MINUTES);
        return ResponseVO.buildSuccessResult(url);
    }

    @GetMapping("/url")
    public ResponseVO<String> getUrl(@RequestParam("fileName") String fileName) {
        String url = minioService.getUrl(fileName, 7, TimeUnit.DAYS);
        return ResponseVO.buildSuccessResult(url);
    }
}

启动服务后使用 Postman 上传成功示例截图如下:

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

解析hash(散列)数据结构

前言 在学习完map、set这两个由红黑树构成的容器后&#xff0c;我们来到了这里hash&#xff0c;首先我们要有一个基础的认知——哈希和map与set的仅在使用时的差别区别&#xff1a;前者内部的元素没有序&#xff0c;而后者有序&#xff0c;其它的都相同&#xff0c;这里我们可…

【C++进阶之路】第一篇:C++中的继承

&#x1f31f;hello&#xff0c;各位读者大大们你们好呀&#x1f31f; &#x1f36d;&#x1f36d;系列专栏&#xff1a;【C学习与应用】 ✒️✒️本篇内容&#xff1a;继承的基础概念&#xff0c;定义方法&#xff0c;基类和派生类的转换&#xff0c;继承中类的作用域&#xf…

VSCode配置React Native调试环境

首先&#xff0c;用VSCode打开新建的react native工程&#xff0c;此时只能运行&#xff0c;是无法调试的。如果想单步调试代码&#xff0c;需要配置。 点击VSCode左边三角形菜单&#xff1a; 点击“创建launch.json文件”&#xff0c; 选择“React Native”调试器&#xff0c;…

肖 sir_就业课__011性能测试讲解

性能测试讲解 一、你做过性能测试吗&#xff1f; 方法1&#xff1a;做过 方法2&#xff1a;在公司中性能测试有专门的性能小组做&#xff0c;但是我也会做性能 二、性能测试有哪些类型&#xff1f; 1&#xff09;压力测试&#xff08;破坏性测试&#xff09; 压力测试是系统在一…

WiFi协议曝安全漏洞:Linux、Android和iOS未能逃脱

来自美国东北大学和鲁汶大学的学者披露了一组IEEE 802.11 Wi-Fi协议标准的一个基础设计漏洞&#xff0c;影响到运行Linux、FreeBSD、Android和iOS的各种设备。 来自美国东北大学和鲁汶大学的学者披露了一组IEEE 802.11 Wi-Fi协议标准的一个基础设计漏洞&#xff0c;影响到运行L…

【C++核心】内存、引用、函数

一、内存四区域 C程序在执行时&#xff0c;将内存大方向划分为4个区域 程序运行前分为&#xff1a; 代码区&#xff1a;存放函数体的二进制代码exe&#xff0c;由操作系统进行管理的 exe机器指令、共享、只读 全局区&#xff1a;存放全局变量和静态变量以及常量&#xff08;字…

运行时内存数据区之虚拟机栈——操作数栈

操作数栈 每一个独立的栈帧中除了包含局部变量表以外&#xff0c;还包含一个后进先出(Last-In-First-Out)的操作数栈&#xff0c;也可以称之为表达式栈(Expression Stack)。操作数栈&#xff0c;在方法执行过程中&#xff0c;根据字节码指令&#xff0c;往栈中写入数据或提取数…

Netty缓冲区ByteBuf源码解析

在网线传输中&#xff0c;字节是基本单位&#xff0c;NIO使用ByteBuffer作为Byte字节容器&#xff0c; 但是其使用过于复杂&#xff0c;因此Netty 写了一套Channel&#xff0c;代替了NIO的Channel &#xff0c;Netty 缓冲区又采用了一套ByteBuffer代替了NIO 的ByteBuffer &…

微服务+springcloud+springcloud alibaba学习笔记【OpenFeign的使用】(5/9)

OpenFeign的使用 5/91、OpenFeign简介1.1、Feign及OpenFeign概念和作用1.2、Feign和OpenFeign区别2、OpenFeign使用步骤2.1、创建Feign消费端微服务2.2、修改POM文件配置2.3、编写yml配置文件2.4、编写主启动类2.5、编写业务类2.5.1、编写 service 层接口&#xff0c;用于服务提…

什么是线性回归?线性回归有什么特征?

什么是线性回归 线性回归定义与公式 线性回归(Linear regression)是利用回归方程(函数)对一个或多个自变量(特征值)和因变量(目标值)之间关系进行建模的一种分析方式。 特点&#xff1a;只有一个自变量的情况称为单变量回归&#xff0c;多于一个自变量情况的叫做多元回归 线…

Orange Pi 5B面世,传承经典,再续传奇

近日&#xff0c;香橙派又出大招。刚刚发布的Orange Pi 5B在性能和表现上再度升级。此前&#xff0c;Orange Pi 5凭借出色的性能和极低的价格被誉为“地表最高性价比开发板”&#xff0c;一经上市就引起市场轰动&#xff0c;销量引领同类产品市场&#xff0c;获得极佳口碑。那么…

【音视频第13天】另外一种拥塞控制算法-TransportCC

目录与Goog-REMB区别TrendLine滤波器与Goog-REMB区别 与Goog-REMB有两个区别&#xff1a; 将拥塞评估算法从接收端移动到了发送端&#xff0c;评估和控制是一体的。TransportCC是发送端评估发送端接着改变码率&#xff0c;REMB是接收端评估&#xff0c;把评估出来的值给发送端…

STL源码剖析-分配器 Allocator

分配器(Allocator) 分配器给容器用的&#xff0c;是一个幕后英雄的角色。分配器的效率非常重要。因为容器必然会使用到分配器来负责内存的分配&#xff0c;它的性能至关重要。 在C中&#xff0c;内存分配和操作通过new和delete完成。 new中包含两个操作&#xff0c;第一步是…

HTML5 Input 类型

文章目录HTML5 Input 类型Input 类型: colorInput 类型: dateInput 类型: datetimeInput 类型: datetime-localInput 类型: emailInput 类型: monthInput 类型: numberInput 类型: rangeInput 类型: searchInput 类型: telInput 类型: timeInput 类型: urlInput 类型: weekHTML…

手撕哈希表

&#x1f308;感谢阅读East-sunrise学习分享——[进阶数据结构]哈希表 博主水平有限&#xff0c;如有差错&#xff0c;欢迎斧正&#x1f64f;感谢有你 码字不易&#xff0c;若有收获&#xff0c;期待你的点赞关注&#x1f499;我们一起进步&#x1f680; &#x1f308;我们上一…

SNN demo

记录一个同门给的SNN demo&#xff0c;仅供自己参考 1 SNN和ANN代码的差别 SNN和ANN的深度学习demo还是差一些的&#xff0c;主要有下面几个&#xff1a; 输入差一个时间维度T&#xff0c;比如&#xff1a;在cv中&#xff0c;ANN的输入是&#xff1a;[B, C, W, H]&#xff0c…

Spring WebFlow-远程代码执行漏洞(CVE-2017-4971)

Spring WebFlow-远程代码执行漏洞&#xff08;CVE-2017-4971&#xff09; 0x00 前言 Spring WebFlow 是一个适用于开发基于流程的应用程序的框架&#xff08;如购物逻辑&#xff09;&#xff0c;可以将流程的定义和实现流程行为的类和视图分离开来。在其 2.4.x 版本中&#x…

浅说情绪控制被杏仁体劫持

2023年4月16号&#xff0c;没想到被杏仁体劫持那么严重&#xff0c;触发手抖和口干的症状&#xff0c;这个还真是自己万万没有想到的。 人生要修炼两条线&#xff1a;一条明线是做的事情&#xff0c;那是自己要做的具体事情。 一条暗线是修炼的自己&#xff0c;这次也做了测试…

云安全——Docker Daemon

0x00 前言 其他云安全相关内容&#xff0c;请参考&#xff1a;云安全知识整理 0x01 Docker Daemon Daemon是Docker的守护进程&#xff0c;Docker Client通过命令行与Docker Damon通信&#xff0c;完成Docker相关操作&#xff0c;2375端口是Daemon的未授权端口。 0x01 2375 …

设计模式之监听模式

本文将会介绍设计模式中的监听模式。   监听模式是一种一对多的关系&#xff0c;可以有任意个&#xff08;一个或多个&#xff09;观察者对象同时监听某一个对象。监听的对象叫观察者&#xff08;Observer&#xff09;&#xff0c;被监听的对象叫作被观察者&#xff08;Obser…