美文网首页spring boot百宝箱Springboot
spring boot集成minio,最新版

spring boot集成minio,最新版

作者: 归来_仍是少年 | 来源:发表于2020-12-11 22:17 被阅读0次

    demo地址:https://github.com/songshijun1995/minio-demo

    1. 使用docker安装minio
    docker run -d -p 9000:9000 -e "MINIO_ACCESS_KEY=admin" -e "MINIO_SECRET_KEY=12345678" -v /storage/data:/data -v /storage/config:/root/.minio --restart=always minio/minio server /data
    

    启动成功后浏览器访问ip:9000


    image.png

    如果配置nginx代理了ip和端口号可以直接访问域名加/minio


    image.png

    进入后点击右下角的+,创建一个桶

    image.png
    然后修改桶的权限为读写(点击三个点,然后选择Edit policy)
    image.png
    image.png
    没安装过docker的可以看我以前的文章,详见
    1. 直接用spring boot官方脚手架创建项目,引入依赖
    <dependency>
        <groupId>io.minio</groupId>
        <artifactId>minio</artifactId>
        <version>8.0.3</version>
    </dependency>
    
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-lang3</artifactId>
    </dependency>
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.6</version>
    </dependency>
    <dependency>
        <groupId>commons-fileupload</groupId>
        <artifactId>commons-fileupload</artifactId>
        <version>1.4</version>
    </dependency>
    
    1. 配置yml
    server:
      port: 8080
      servlet:
        context-path: /
    
    spring:
      application:
        name: minio-demo
    
    minio:
      endpoint: http://129.28.158.207:9000
      accessKey: admin
      secretKey: 12345678
      filHost: http://file.songshijun.top
    
    logging:
      level:
        ROOT: info
        com.minio: debug
      pattern:
        file: '%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level [%thread] %logger{50} - %msg%n'
      file:
        name: ${logging.file.path}/${spring.application.name}.log
        path: /home/logs/${spring.application.name}
        max-size: 10MB
        max-history: 30
    

    4.新建MinioProp类和MinioConfig类,分别加载minio账号密码以及初始MinioClient

    package com.minio.config;
    
    import lombok.Data;
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.stereotype.Component;
    
    @Data
    @Component
    @ConfigurationProperties(prefix = "minio")
    public class MinioProp {
        /**
         * 连接地址
         */
        private String endpoint;
        /**
         * 用户名
         */
        private String accessKey;
        /**
         * 密码
         */
        private String secretKey;
        /**
         * 域名
         */
        private String filHost;
    }
    
    package com.minio.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(MinioProp.class)
    public class MinioConfig {
    
        @Autowired
        private MinioProp minioProp;
    
        /**
         * 获取MinioClient
         */
        @Bean
        public MinioClient minioClient() {
            return MinioClient.builder()
                            .endpoint(minioProp.getEndpoint())
                            .credentials(minioProp.getAccessKey(), minioProp.getSecretKey())
                            .build();
        }
    
    }
    
    package com.minio.dto.response;
    
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class FileUploadResponse {
        private String urlHttp;
    
        private String urlPath;
    }
    

    5.新建工具类MinioUtil,用来封装上传和删除文件等方法

    package com.minio.utils;
    
    import com.minio.config.MinioProp;
    import com.minio.dto.response.FileUploadResponse;
    import io.minio.*;
    import io.minio.errors.*;
    import io.minio.messages.Bucket;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Component;
    import org.springframework.web.multipart.MultipartFile;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.security.InvalidKeyException;
    import java.security.NoSuchAlgorithmException;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.List;
    import java.util.Optional;
    import java.util.Random;
    
    @Slf4j
    @Component
    public class MinioUtil {
    
        @Autowired
        private MinioProp minioProp;
    
        @Autowired
        private MinioClient client;
    
        /**
         * 创建bucket
         */
        public void createBucket(String bucketName) throws Exception {
            if (!client.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build())) {
                client.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
            }
        }
    
        /**
         * 上传文件
         */
        public FileUploadResponse uploadFile(MultipartFile file, String bucketName) throws Exception {
            //判断文件是否为空
            if (null == file || 0 == file.getSize()) {
                return null;
            }
            //判断存储桶是否存在  不存在则创建
            createBucket(bucketName);
            //文件名
            String originalFilename = file.getOriginalFilename();
            //新的文件名 = 存储桶文件名_时间戳.后缀名
            assert originalFilename != null;
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
            String fileName = bucketName + "_" +
                    System.currentTimeMillis() + "_" + format.format(new Date()) + "_" + new Random().nextInt(1000) +
                    originalFilename.substring(originalFilename.lastIndexOf("."));
            //开始上传
            client.putObject(
                    PutObjectArgs.builder().bucket(bucketName).object(fileName).stream(
                            file.getInputStream(), file.getSize(), -1)
                            .contentType(file.getContentType())
                            .build());
            String url = minioProp.getEndpoint() + "/" + bucketName + "/" + fileName;
            String urlHost = minioProp.getFilHost() + "/" + bucketName + "/" + fileName;
            log.info("上传文件成功url :[{}], urlHost :[{}]", url, urlHost);
            return new FileUploadResponse(url, urlHost);
        }
    
        /**
         * 获取全部bucket
         *
         * @return
         */
        public List<Bucket> getAllBuckets() throws Exception {
            return client.listBuckets();
        }
    
        /**
         * 根据bucketName获取信息
         *
         * @param bucketName bucket名称
         */
        public Optional<Bucket> getBucket(String bucketName) throws IOException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException, InvalidResponseException, InternalException, ErrorResponseException, ServerException, XmlParserException {
            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 expires    过期时间 <=7
         * @return url
         */
        public String getObjectURL(String bucketName, String objectName, Integer expires) throws Exception {
            return client.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 client.getObject(GetObjectArgs.builder().bucket(bucketName).object(objectName).build());
        }
    
        /**
         * 上传⽂件
         *
         * @param bucketName bucket名称
         * @param objectName ⽂件名称
         * @param stream     ⽂件流
         * @throws Exception https://docs.minio.io/cn/java-client-api-reference.html#putObject
         */
        public void putObject(String bucketName, String objectName, InputStream stream) throws
                Exception {
            client.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-client-api-reference.html#putObject
         */
        public void putObject(String bucketName, String objectName, InputStream stream, long
                size, String contextType) throws Exception {
            client.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-client-api-reference.html#statObject
         */
        public StatObjectResponse getObjectInfo(String bucketName, String objectName) throws Exception {
            return client.statObject(StatObjectArgs.builder().bucket(bucketName).object(objectName).build());
        }
    
        /**
         * 删除⽂件
         *
         * @param bucketName bucket名称
         * @param objectName ⽂件名称
         * @throws Exception https://docs.minio.io/cn/java-client-apireference.html#removeObject
         */
        public void removeObject(String bucketName, String objectName) throws Exception {
            client.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(objectName).build());
        }
    }
    

    6.新建MinioController

    package com.minio.controller;
    
    import com.minio.dto.response.FileUploadResponse;
    import com.minio.utils.MinioUtil;
    import io.minio.errors.MinioException;
    import lombok.extern.slf4j.Slf4j;
    import org.apache.commons.lang3.StringUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.http.HttpHeaders;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.ResponseEntity;
    import org.springframework.web.bind.annotation.*;
    import org.springframework.web.multipart.MultipartFile;
    
    import javax.servlet.ServletOutputStream;
    import javax.servlet.http.HttpServletResponse;
    import java.io.ByteArrayOutputStream;
    import java.io.InputStream;
    import java.util.Arrays;
    
    @Slf4j
    @RestController
    @RequestMapping("/file")
    public class MinioController {
    
        @Autowired
        private MinioUtil minioUtil;
    
        /**
         * 上传文件
         */
        @PostMapping("/upload")
        public FileUploadResponse upload(@RequestParam(name = "file", required = false) MultipartFile file, @RequestParam(required = false) String bucketName) {
            FileUploadResponse response = null;
            if (StringUtils.isBlank(bucketName)) {
                bucketName = "salt";
            }
            try {
                response = minioUtil.uploadFile(file, bucketName);
            } catch (Exception e) {
                log.error("上传失败 : [{}]", Arrays.asList(e.getStackTrace()));
            }
            return response;
        }
    
        /**
         * 删除文件
         */
        @DeleteMapping("/delete/{objectName}")
        public void delete(@PathVariable("objectName") String objectName, @RequestParam(required = false) String bucketName) throws Exception {
            if (StringUtils.isBlank(bucketName)) {
                bucketName = "salt";
            }
            minioUtil.removeObject(bucketName, objectName);
            System.out.println("删除成功");
        }
    
        /**
         * 下载文件到本地
         */
        @GetMapping("/download/{objectName}")
        public ResponseEntity<byte[]> downloadToLocal(@PathVariable("objectName") String objectName, HttpServletResponse response) throws Exception {
            ResponseEntity<byte[]> responseEntity = null;
            InputStream stream = null;
            ByteArrayOutputStream output = null;
            try {
                // 获取"myobject"的输入流。
                stream = minioUtil.getObject("salt", objectName);
                if (stream == null) {
                    System.out.println("文件不存在");
                }
                //用于转换byte
                output = new ByteArrayOutputStream();
                byte[] buffer = new byte[4096];
                int n = 0;
                while (-1 != (n = stream.read(buffer))) {
                    output.write(buffer, 0, n);
                }
                byte[] bytes = output.toByteArray();
    
                //设置header
                HttpHeaders httpHeaders = new HttpHeaders();
                httpHeaders.add("Accept-Ranges", "bytes");
                httpHeaders.add("Content-Length", bytes.length + "");
    //            objectName = new String(objectName.getBytes("UTF-8"), "ISO8859-1");
                //把文件名按UTF-8取出并按ISO8859-1编码,保证弹出窗口中的文件名中文不乱码,中文不要太多,最多支持17个中文,因为header有150个字节限制。
                httpHeaders.add("Content-disposition", "attachment; filename=" + objectName);
                httpHeaders.add("Content-Type", "text/plain;charset=utf-8");
    //            httpHeaders.add("Content-Type", "image/jpeg");
                responseEntity = new ResponseEntity<byte[]>(bytes, httpHeaders, HttpStatus.CREATED);
    
            } catch (MinioException e) {
                e.printStackTrace();
            } finally {
                if (stream != null) {
                    stream.close();
                }
                if (output != null) {
                    output.close();
                }
            }
            return responseEntity;
        }
    
        /**
         * 在浏览器预览图片
         */
        @GetMapping("/preViewPicture/{objectName}")
        public void preViewPicture(@PathVariable("objectName") String objectName, HttpServletResponse response) throws Exception {
            response.setContentType("image/jpeg");
            try (ServletOutputStream out = response.getOutputStream()) {
                InputStream stream = minioUtil.getObject("salt", objectName);
                ByteArrayOutputStream output = new ByteArrayOutputStream();
                byte[] buffer = new byte[4096];
                int n = 0;
                while (-1 != (n = stream.read(buffer))) {
                    output.write(buffer, 0, n);
                }
                byte[] bytes = output.toByteArray();
                out.write(bytes);
                out.flush();
            }
        }
    }
    

    7.启动项目用postman测试上传文件


    image.png
    image.png
    image.png

    8.项目最新版集成swagger2,方便大家测试,可以看看README.md文件


    image.png

    相关文章

      网友评论

        本文标题:spring boot集成minio,最新版

        本文链接:https://www.haomeiwen.com/subject/rmysgktx.html