首页>>后端>>SpringBoot->SpringBoot 整合 Minio 上传文件

SpringBoot 整合 Minio 上传文件

时间:2023-12-01 本站 点击:0

Minio

上传文件如果不使用云服务的话,需要本地搭建,一般选择 FastDFS 但是 FastDFS 安装比较复杂,今天了解一款安装使用更简单的存储系统 MinIO

MinIO 是一款高性能、分布式的对象存储系统. 它是一款软件产品, 可以100%的运行在标准硬件。即X86等低成本机器也能够很好的运行MinIO。

MinIO与传统的存储和其他的对象存储不同的是:它一开始就针对性能要求更高的私有云标准进行软件架构设计。因为MinIO一开始就只为对象存储而设计。所以他采用了更易用的方式进行设计,它能实现对象存储所需要的全部功能,在性能上也更加强劲,它不会为了更多的业务功能而妥协,失去MinIO的易用性、高效性。 这样的结果所带来的好处是:它能够更简单的实现局有弹性伸缩能力的原生对象存储服务。

MinIO在传统对象存储用例(例如辅助存储,灾难恢复和归档)方面表现出色。同时,它在机器学习、大数据、私有云、混合云等方面的存储技术上也独树一帜。当然,也不排除数据分析、高性能应用负载、原生云的支持。

在中国:阿里巴巴、腾讯、百度、中国联通、华为、中国移动等等9000多家企业也都在使用MinIO产品

安装 Minio

使用docker安装

拉取镜像

docker pull minio/minio

启动

docker run -p 9000:9000 -p 9001:9001 -d --name minio -v /opt/docker/minio/data:/data -v /opt/docker/minio/config:/root/.minio -e "MINIO_ROOT_USER=minio" -e "MINIO_ROOT_PASSWORD=minio@123456" minio/minio server /data --console-address ":9000" --address ":9001"

使用9000端口 登录控制台

创建存储桶

设置桶权限

创建 Java 客户端

依赖

<dependencies>    <dependency>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-web</artifactId>    </dependency>    <dependency>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-starter-test</artifactId>        <scope>test</scope>        <exclusions>            <exclusion>                <groupId>org.junit.vintage</groupId>                <artifactId>junit-vintage-engine</artifactId>            </exclusion>        </exclusions>    </dependency>    <dependency>        <groupId>org.springframework.boot</groupId>        <artifactId>spring-boot-configuration-processor</artifactId>        <optional>true</optional>    </dependency>    <dependency>        <groupId>org.projectlombok</groupId>        <artifactId>lombok</artifactId>        <optional>true</optional>    </dependency>    <!-- minio依赖       -->    <dependency>        <groupId>io.minio</groupId>        <artifactId>minio</artifactId>        <version>8.2.1</version>    </dependency>    <!-- hutool工具类       -->    <dependency>        <groupId>cn.hutool</groupId>        <artifactId>hutool-all</artifactId>        <version>5.1.2</version>    </dependency>    <!-- 压缩图片       -->    <dependency>        <groupId>net.coobird</groupId>        <artifactId>thumbnailator</artifactId>        <version>0.4.8</version>    </dependency>    <!--    工具类依赖    -->    <dependency>        <groupId>org.apache.commons</groupId>        <artifactId>commons-lang3</artifactId>        <version>3.12.0</version>    </dependency>    <dependency>        <groupId>com.github.davidcarboni</groupId>        <artifactId>encrypted-</artifactId>        <version>1.0.0</version>    </dependency></dependencies>

配置文件

spring:  application:    name: minio-demo  servlet:    multipart:      max-file-size: 20MB      max-request-size: 200MBserver:  port: 8088minio:  endpoint: http://你的ip:9001  accessKey: minio  secretKey: minio@123456  nginxHost: http://你的域名

配置文件配置类

package com.sqm.minio_demo.config;import lombok.Data;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.stereotype.Component;@ConfigurationProperties(prefix = "minio")@Component@Datapublic class MinioProperties {    /**     * 连接地址     */    private String endpoint;    /**     * 用户名     */    private String accessKey;    /**     * 密码     */    private String secretKey;    /**     * 域名     */    private String nginxHost;}

创建 minio 客户端

package com.sqm.minio_demo.config;import io.minio.MinioClient;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.boot.context.properties.EnableConfigurationProperties;import org.springframework.context.annotation.Bean;import org.springframework.context.annotation.Configuration;@Configuration@EnableConfigurationProperties(MinioProperties.class)public class MinioConfig {    @Autowired    private MinioProperties minioProperties;    @Bean    public MinioClient minioClient(){        return MinioClient.builder()                .endpoint(minioProperties.getEndpoint())                .credentials(minioProperties.getAccessKey(),minioProperties.getSecretKey())                .build();    }}

文件地址返回路径实体类

package com.sqm.minio_demo.entity;import lombok.AllArgsConstructor;import lombok.Data;import lombok.NoArgsConstructor;@Data@NoArgsConstructor@AllArgsConstructorpublic class UploadResponse {    private String minIoUrl;    private String nginxUrl;}

上传文件工具类

package com.sqm.minio_demo.util;import cn.hutool.core.date.DateUtil;import com.sqm.minio_demo.config.MinioProperties;import com.sqm.minio_demo.entity.UploadResponse;import io.minio.*;import io.minio.errors.*;import io.minio.messages.Bucket;import lombok.extern.slf4j.Slf4j;import net.coobird.thumbnailator.Thumbnails;import org.apache.commons.fileupload.FileItem;import org.apache.commons.fileupload.FileItemFactory;import org.apache.commons.fileupload.disk.DiskFileItemFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Component;import org.springframework.web.multipart.MultipartFile;import org.springframework.web.multipart.commons.CommonsMultipartFile;import java.io.File;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.security.InvalidKeyException;import java.security.NoSuchAlgorithmException;import java.util.List;import java.util.Optional;import java.util.Random;@Component@Slf4jpublic class MinioUtil {    @Autowired    private MinioProperties minioProperties;    @Autowired    private MinioClient minioClient;    private final Long maxSize = (long) (1024 * 1024);    /**     * 创建bucket     */    public void createBucket(String bucketName) throws Exception {        if (!minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())) {            minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());        }    }    /**     * 上传文件     */    public UploadResponse uploadFile(MultipartFile file, String bucketName) throws Exception {        //判断文件是否为空        if (null == file || 0 == file.getSize()) {            return null;        }        //判断存储桶是否存在  不存在则创建        createBucket(bucketName);        //文件名        String originalFilename = file.getOriginalFilename();        //新的文件名 = 时间戳_随机数.后缀名        assert originalFilename != null;        long now = System.currentTimeMillis() / 1000;        String fileName = DateUtil.format(DateUtil.date(),"yyyyMMdd")+"_"+ now + "_" + new Random().nextInt(1000) +                originalFilename.substring(originalFilename.lastIndexOf("."));        //开始上传        log.info("file压缩前大小:{}",file.getSize());        if (file.getSize() > maxSize) {            FileItemFactory fileItemFactory = new DiskFileItemFactory();            FileItem fileItem = fileItemFactory.createItem(fileName, "text/plain", true, fileName);            OutputStream outputStream = fileItem.getOutputStream();            Thumbnails.of(file.getInputStream()).scale(1f).outputFormat(originalFilename.substring(originalFilename.lastIndexOf(".")+1)).outputQuality(0.25f).toOutputStream(outputStream);            file = new CommonsMultipartFile(fileItem);        }        log.info("file压缩后大小:{}",file.getSize());        minioClient.putObject(                PutObjectArgs.builder().bucket(bucketName).object(fileName).stream(                        file.getInputStream(), file.getSize(), -1)                        .contentType(file.getContentType())                        .build());        String url = minioProperties.getEndpoint() + "/" + bucketName + "/" + fileName;        String urlHost = minioProperties.getNginxHost() + "/" + bucketName + "/" + fileName;        return new UploadResponse(url, urlHost);    }    /**     * 获取全部bucket     *     * @return     */    public List<Bucket> getAllBuckets() throws Exception {        return minioClient.listBuckets();    }    /**     * 根据bucketName获取信息     *     * @param bucketName bucket名称     */    public Optional<Bucket> getBucket(String bucketName) throws IOException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException, InvalidResponseException, InternalException, ErrorResponseException, ServerException, XmlParserException, ServerException {        return minioClient.listBuckets().stream().filter(b -> b.name().equals(bucketName)).findFirst();    }    /**     * 根据bucketName删除信息     *     * @param bucketName bucket名称     */    public void removeBucket(String bucketName) throws Exception {        minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());    }    /**     * 获取⽂件外链     *     * @param bucketName bucket名称     * @param objectName ⽂件名称     * @param expires    过期时间 <=7     * @return url     */    public String getObjectURL(String bucketName, String objectName, Integer expires) throws Exception {        return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().bucket(bucketName).object(objectName).expiry(expires).build());    }    /**     * 获取⽂件     *     * @param bucketName bucket名称     * @param objectName ⽂件名称     * @return ⼆进制流     */    public InputStream getObject(String bucketName, String objectName) throws Exception {        return minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(objectName).build());    }    /**     * 上传⽂件     *     * @param bucketName bucket名称     * @param objectName ⽂件名称     * @param stream     ⽂件流     * @throws Exception https://docs.minio.io/cn/java-minioClient-api-reference.html#putObject     */    public void putObject(String bucketName, String objectName, InputStream stream) throws            Exception {        minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(objectName).stream(stream, stream.available(), -1).contentType(objectName.substring(objectName.lastIndexOf("."))).build());    }    /**     * 上传⽂件     *     * @param bucketName  bucket名称     * @param objectName  ⽂件名称     * @param stream      ⽂件流     * @param size        ⼤⼩     * @param contextType 类型     * @throws Exception https://docs.minio.io/cn/java-minioClient-api-reference.html#putObject     */    public void putObject(String bucketName, String objectName, InputStream stream, long            size, String contextType) throws Exception {        minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(objectName).stream(stream, size, -1).contentType(contextType).build());    }    /**     * 获取⽂件信息     *     * @param bucketName bucket名称     * @param objectName ⽂件名称     * @throws Exception https://docs.minio.io/cn/java-minioClient-api-reference.html#statObject     */    public StatObjectResponse getObjectInfo(String bucketName, String objectName) throws Exception {        return minioClient.statObject(StatObjectArgs.builder().bucket(bucketName).object(objectName).build());    }    /**     * 删除⽂件     *     * @param bucketName bucket名称     * @param objectName ⽂件名称     * @throws Exception https://docs.minio.io/cn/java-minioClient-apireference.html#removeObject     */    public void removeObject(String bucketName, String objectName) throws Exception {        minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(objectName).build());    }    /***     * 上传视频     * @param file     * @param bucketName     * @return     * @throws Exception     */    public UploadResponse uploadVideo(MultipartFile file, String bucketName) throws Exception {        //判断文件是否为空        if (null == file || 0 == file.getSize()) {            return null;        }        //判断存储桶是否存在  不存在则创建        createBucket(bucketName);        //文件名        String originalFilename = file.getOriginalFilename();        //新的文件名 = 时间戳_随机数.后缀名        assert originalFilename != null;        long now = System.currentTimeMillis() / 1000;        String fileName = DateUtil.format(DateUtil.date(),"yyyyMMdd")+"_"+ now + "_" + new Random().nextInt(1000) +                originalFilename.substring(originalFilename.lastIndexOf("."));        //开始上传        log.info("file大小:{}",file.getSize());        minioClient.putObject(                PutObjectArgs.builder().bucket(bucketName).object(fileName).stream(                        file.getInputStream(), file.getSize(), -1)                        .contentType("video/mp4")                        .build());        String url = minioProperties.getEndpoint() + "/" + bucketName + "/" + fileName;        String urlHost = minioProperties.getNginxHost() + "/" + bucketName + "/" + fileName;        return new UploadResponse(url, urlHost);    }}

测试上传文件 Controller

package com.sqm.minio_demo.controller;import com.sqm.minio_demo.entity.ResultData;import com.sqm.minio_demo.entity.UploadResponse;import com.sqm.minio_demo.util.MinioUtil;import lombok.extern.slf4j.Slf4j;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.bind.annotation.PostMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.RestController;import org.springframework.web.multipart.MultipartFile;@RestController@Slf4jpublic class TestController {    @Autowired    private MinioUtil minioUtil;    /**     * @author: xx     * @date: 2022/5/25 15:32     * @description: 上传文件     */    @PostMapping("/upload")    public ResultData minioUpload(@RequestParam(value = "file") MultipartFile file){        UploadResponse response = null;        try {            response = minioUtil.uploadFile(file, "bucket01");        } catch (Exception e) {            log.error("上传失败",e);        }        return ResultData.ok(response);    }    /**     * @author: xx     * @date: 2022/5/25 15:32     * @description: 上传视频     */    @PostMapping("/uploadVideo")    public ResultData uploadVideo(@RequestParam(value = "file") MultipartFile file){        UploadResponse response = null;        try {            response = minioUtil.uploadVideo(file, "video-test");        } catch (Exception e) {            log.error("上传失败",e);        }        return ResultData.ok(response);    }}

测试上传

控制台也可以看到上传的视频

原文:https://juejin.cn/post/7101581935486615559


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