likes
comments
collection
share

使用springboot+mysql+minio+nacos做个自己的OSS微服务

作者站长头像
站长
· 阅读数 18

本文皆为个人原创,请尊重创作,未经许可不得转载。

什么是OSS

OSS工作原理

数据以对象(Object)的形式存储在OSS的存储空间(Bucket )中。如果要使用OSS存储数据,您需要先创建Bucket,并指定Bucket的地域、访问权限、存储类型等属性。创建Bucket后,您可以将数据以Object的形式上传到Bucket,并指定Object的文件名(Key)作为其唯一标识。

OSS以HTTP RESTful API的形式对外提供服务,访问不同地域需要不同的访问域名(Endpoint)。当您请求访问OSS时,OSS通过使用访问密钥(AccessKey ID和AccessKey Secret)对称加密的方法来验证某个请求的发送者身份。

来源:阿里云help.aliyun.com/zh/oss/prod…

minio

MinIO 是一种高性能、S3 兼容的对象存储。 它专为大规模 AI/ML、数据湖和数据库工作负载而构建,并且它是由软件定义的存储。 不需要购买任何专有硬件,就可以在云上和普通硬件上拥有分布式对象存储。 MinIO拥有开源 GNU AGPL v3 和商业企业许可证的双重许可。

中文文档地址:www.minio.org.cn/docs/minio/…

项目

此项目已上传Github托管,欢迎提交PR或Issues。

集成

springboot 2.x

nacos 2.x

thumbnailator 0.4.9

mybatis-plus 3.4.1

minio 8.5.4

项目目录结构

├─createtable.txt # 建表语句
├─pom.xml
├─README.md
├─src
|  ├─main
|  |  ├─resources
|  |  |     ├─application.yml 
|  |  |     ├─bootstrap-exapmle.yml # 参考配置文件
|  |  |     ├─bootstrap.yml #
|  |  |     └logback.xml
|  |  ├─java
|  |  |  ├─Application.java
|  |  |  ├─com
|  |  |  |  ├─nott
|  |  |  |  |  ├─minio
|  |  |  |  |  |   ├─MinioTemplate.java # 包装Minio的操作类
|  |  |  |  |  |   ├─propertie
|  |  |  |  |  |   |     └MinioProp.java # minio属性配置
|  |  |  |  |  ├─file
|  |  |  |  |  |  ├─service
|  |  |  |  |  |  |    └FileService.java  # oss服务层
|  |  |  |  |  |  ├─mapper
|  |  |  |  |  |  |   └SysMinioFileMapper.java  # oss数据交互层
|  |  |  |  |  |  ├─entity
|  |  |  |  |  |  |   └SysMinioFile.java # oss实体
|  |  |  |  |  |  ├─controller
|  |  |  |  |  |  |     └FileController.java # oss文件操作控制层
|  |  |  |  |  ├─config
|  |  |  |  |  |   ├─CorsConfig.java
|  |  |  |  |  |   └MybatisPlusConfig.java
|  |  |  |  |  ├─common
|  |  |  |  |  |   ├─CommonPageService.java # 简单的mybatis-plus条件构造生成
|  |  |  |  |  |   ├─ExceptionHandler.java
|  |  |  |  |  |   ├─R.java # 统一结果类
|  |  |  |  |  |   └ThreadPoolContext.java

具体实现

整个系统整合的就是与minio服务端交互、在数据库(mysql)生成对应文件记录的过程,交互时客户端使用文件记录的id进行操作。

MinioTemplate

public class MinioTemplate {

    private final Logger log = LoggerFactory.getLogger(MinioTemplate.class);

    private MinioClient client;
    @Resource
    private MinioProp minioProp;
    @Value("${upload.maxSize}")
    private long maxSize;
    @Value("${upload.compress}")
    private boolean compress;

    @Value("${minio.autocreate}")
    public boolean autoCreate;
    
    public MinioClient getClient() throws Exception {
        if (this.client == null) {
            MinioClient minioClient =
                    MinioClient.builder()
                            .endpoint(minioProp.getUrl(), minioProp.getPort(), false)
                            .credentials(minioProp.getUsername(), minioProp.getPassword())
                            .build();
            if (minioClient == null) {
                throw new RuntimeException("链接远程Minio服务端失败");
            }
            this.client = minioClient;
        }
        boolean found = client.bucketExists(BucketExistsArgs.builder().bucket(minioProp.getBucket()).build());
        if (!found) {
            if (autoCreate) {
                client.makeBucket(MakeBucketArgs.builder().bucket(minioProp.getBucket()).build());
                log.info("Auto make bucket: {}", minioProp.getBucket());
            } else {
                throw new RuntimeException(String.format("没有找到Bucket:[%s]", minioProp.getBucket()));
            }
        }

        return this.client;
    }
      // 上传
    public String upload(MultipartFile file, String holderCode) throws Exception {
        if (file == null) {
            throw new RuntimeException("文件不能为空");
        }

        boolean isPic = this.isPicture(file);
        String filePath = "";
        String uuidFileName = UUID.randomUUID().toString();
        if (StringUtils.isNotEmpty(holderCode)) {
            filePath = holderCode + "/" + uuidFileName;
        } else {
            filePath = uuidFileName;
        }
        MinioClient minioClient = getClient();
        // 如果是图片则压缩
        if (isPic && compress) {
            file = this.handlePicCompress(file);
        }
        InputStream inputStream = file.getInputStream();
        minioClient.putObject(
                PutObjectArgs.builder().bucket(minioProp.getBucket()).object(filePath)
                        .contentType(file.getContentType())
                        .stream(
                                inputStream, inputStream.available(), -1)
                        .build());
        log.info("File {},Upload Bucket {}", uuidFileName, minioProp.getBucket());
        return uuidFileName;
    }
    // 下载、删除 ...
    }

FileController

提供oss中Http交互的功能


@RestController
@RequestMapping("file")
public class FileController {

    @Resource
    private FileService fileService;
    @Resource
    private CommonPageService<SysMinioFile> commonPageService;

    @PostMapping("upload")
    public R fileUpload(@RequestParam("file") MultipartFile file, String holderCode) throws Exception {
        if (file == null) {
            return R.failure("文件为空");
        }
        return R.okData(fileService.uploadFile(file, holderCode));
    }

    @RequestMapping("preview/{id}")
    public R preview(@NotNull @PathVariable("id") String id) throws Exception {
        String url = fileService.preview(id);
        return R.okData(url);
    }
    ...

启动minio服务

以Windows本地测试为例,先在本地运行minio服务端。

注:如果是第一次启动,需要设置minio的用户和密码。

$ minio.exe server testData --console-address :9090
使用springboot+mysql+minio+nacos做个自己的OSS微服务

启动输出

使用springboot+mysql+minio+nacos做个自己的OSS微服务

进入管理后台

启动nacos

运行nacos并创建对应的命名空间和配置文件

使用springboot+mysql+minio+nacos做个自己的OSS微服务

项目已创建供参考的配置文件,bootstrap-exapmle.yml

测试

测试上传接口

使用springboot+mysql+minio+nacos做个自己的OSS微服务

预览接口

使用springboot+mysql+minio+nacos做个自己的OSS微服务

下载接口

使用springboot+mysql+minio+nacos做个自己的OSS微服务

本文皆为个人原创,请尊重创作,未经许可不得转载。

转载自:https://juejin.cn/post/7362547971060056102
评论
请登录