zoukankan      html  css  js  c++  java
  • docker安装minIO并整合springboot

    简介

    Minio是Apache License v2.0下发布的对象存储服务器。它与Amazon S3云存储服务兼容。它最适合存储非结构化数据,如照片,视频,日志文件,备份和容器/ VM映像。对象的大小可以从几KB到最大5TBMinio服务器足够轻,可以与应用程序堆栈捆绑在一起,类似于NodeJS,Redis和MySQL。https://docs.minio.io/

    使用分布式文件服务FASTDFS和阿里云的OSS对象存储来存文件。奈何OSS太贵,FASTDFS搭建配置又太繁琐,推荐高性能对象存储服务MinIO。

    Docker安装

    docker pull minio/minio
    docker run -p 9000:9000 --name minio 
      -e "MINIO_ACCESS_KEY=minio" 
      -e "MINIO_SECRET_KEY=gulimall_minio" 
      -v /mydata/minio/data:/data 
      -v /mydata/minio/config:/root/.minio 
      -d minio/minio server /data
    
    存储桶命名规则

    以下规则适用于命名 S3 存储桶:

    • 存储桶名称必须长在 3 到 63 个字符之间。
    • 存储桶名称只能由小写字母、数字、点 (.) 和连字符 (-) 组成。
    • 存储桶名称必须以字母或数字开头和结尾。
    • 存储桶名称不得格式化为 IP 地址(例如,192.168.5.4)。
    • 存储桶名称在分区中必须是唯一的。分区是区域的分组。AWS 目前有三个分区:(标准区域)、(中国区域)和(AWS GovCloud [美国]区域)。awsaws-cnaws-us-gov
    • 与 Amazon S3 传输加速一起使用的存储桶的名称中不能有点 (.)。有关传输加速的详细信息,请参阅亚马逊S3 传输加速。

    java客户端使用

    依赖:

    <dependency>
        <groupId>io.minio</groupId>
        <artifactId>minio</artifactId>
        <version>7.0.2</version>
    </dependency>
    

    application.yml配置

    # 图片服务器 minio配置
    minio:
      ip: xxxxxxx:9000
      # minio登录账号密码
      accessKey: xxxxxxx
      secretKey: xxxxxxxx
     
      ## 桶名(文件夹)命名规则要符合 亚马逊S3标准 详情可看http://docs.aws.amazon.com/AmazonS3/latest/dev/BucketRestrictions.html
      bucketName:
        ## 照片文件夹
        facility: facility-photos
    

    操作API 类

    /**
     * @author zhan
     * @since 2020-05-18 11:23
     */
    @Slf4j
    public class Minio {
    
        /**
         * 服务器地址
         */
        @Value("${minio.ip}")
        private String ip;
    
        /**
         * 登录账号
         */
        @Value("${minio.accessKey}")
        private String accessKey;
    
        /**
         * 登录密码
         */
        @Value("${minio.secretKey}")
        private String secretKey;
    
        /**
         * 缩略图大小
         */
        @Value("${minio.thumbor.width}")
        private String thumborWidth;
    
    
        /**
         * Minio文件上传
         *
         * @param file       文件实体
         * @param fileName   修饰过的文件名 非源文件名
         * @param bucketName 所存文件夹(桶名)
         * @return
         */
        public R minioUpload(MultipartFile file, String fileName, String bucketName) {
            try {
                MinioClient minioClient = new MinioClient("http://" + ip, accessKey, secretKey);
                boolean bucketExists = minioClient.bucketExists(bucketName);
                if (bucketExists) {
                    log.info("仓库" + bucketName + "已经存在,可直接上传文件。");
                } else {
                    minioClient.makeBucket(bucketName);
                }
                if (file.getSize() <= 20971520) {
                    // fileName为空,说明要使用源文件名上传
                    if (fileName == null) {
                        fileName = file.getOriginalFilename();
                        fileName = fileName.replaceAll(" ", "_");
                    }
                    // minio仓库名
                    minioClient.putObject(bucketName, fileName, file.getInputStream(), file.getContentType());
                    log.info("成功上传文件 " + fileName + " 至 " + bucketName);
                    String fileUrl = bucketName + "/" + fileName;
                    Map<String, Object> map = new HashMap<String, Object>();
                    map.put("fileUrl", fileUrl);
                    map.put("bucketName", bucketName);
                    map.put("originFileName", fileName);
                    return R.ok(map);
                } else {
                    throw new Exception("请上传小于20mb的文件");
                }
            } catch (Exception e) {
                e.printStackTrace();
                if (e.getMessage().contains("ORA")) {
                    return R.error("上传失败:【查询参数错误】");
                }
                return R.error("上传失败:【" + e.getMessage() + "】");
            }
        }
    
        /**
         * 判断文件是否存在
         *
         * @param fileName   文件名
         * @param bucketName 桶名(文件夹)
         * @return
         */
        public boolean isFileExisted(String fileName, String bucketName) {
            InputStream inputStream = null;
            try {
                MinioClient minioClient = new MinioClient("http://" + ip, accessKey, secretKey);
                inputStream = minioClient.getObject(bucketName, fileName);
                if (inputStream != null) {
                    return true;
                }
            } catch (Exception e) {
                return false;
            } finally {
                if (inputStream != null) {
                    try {
                        inputStream.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            return false;
        }
    
        /**
         * 删除文件
         *
         * @param bucketName 桶名(文件夹)
         * @param fileName   文件名
         * @return
         */
        public boolean delete(String bucketName, String fileName) {
            try {
                MinioClient minioClient = new MinioClient("http://" + ip, accessKey, secretKey);
                minioClient.removeObject(bucketName, fileName);
                return true;
            } catch (Exception e) {
                log.error(e.getMessage());
                return false;
            }
        }
    
        /**
         * 下载文件
         *
         * @param objectName 文件名
         * @param bucketName 桶名(文件夹)
         * @param response
         * @return
         */
        public R downloadFile(String objectName, String bucketName, HttpServletResponse response) {
            try {
                MinioClient minioClient = new MinioClient("http://" + ip, accessKey, secretKey);
                InputStream file = minioClient.getObject(bucketName, objectName);
                String filename = new String(objectName.getBytes("ISO8859-1"), StandardCharsets.UTF_8);
                response.setHeader("Content-Disposition", "attachment;filename=" + filename);
                ServletOutputStream servletOutputStream = response.getOutputStream();
                int len;
                byte[] buffer = new byte[1024];
                while ((len = file.read(buffer)) > 0) {
                    servletOutputStream.write(buffer, 0, len);
                }
                servletOutputStream.flush();
                file.close();
                servletOutputStream.close();
                return R.ok(objectName + "下载成功");
            } catch (Exception e) {
                e.printStackTrace();
                if (e.getMessage().contains("ORA")) {
                    return R.error("下载失败:【查询参数错误】");
                }
                return R.error("下载失败:【" + e.getMessage() + "】");
            }
        }
    
        /**
         * 获取文件流
         *
         * @param objectName 文件名
         * @param bucketName 桶名(文件夹)
         * @return
         */
        public InputStream getFileInputStream(String objectName, String bucketName) {
            try {
                MinioClient minioClient = new MinioClient("http://" + ip, accessKey, secretKey);
                return minioClient.getObject(bucketName, objectName);
            } catch (Exception e) {
                e.printStackTrace();
                log.error(e.getMessage());
            }
            return null;
        }
    }
    

    springboot整合Minio
    1. 导入依赖
    <!-- https://mvnrepository.com/artifact/com.jlefebure/spring-boot-starter-minio -->
            <dependency>
                <groupId>com.jlefebure</groupId>
                <artifactId>spring-boot-starter-minio</artifactId>
                <version>1.4</version>
            </dependency>
    
    1. 配置yml
    spring:
      minio:
        url: http://192.168.1.119:9000/
        access-key: minio
        secret-key: gulimall_minio
        bucket: gulimall
        create-bucket: true
    
    1. 直接在controller中使用
    package com.atguigu.gulimall.product.controller;
    
    import com.jlefebure.spring.boot.minio.MinioConfigurationProperties;
    import com.jlefebure.spring.boot.minio.MinioService;
    import io.minio.messages.Item;
    import org.apache.tomcat.util.http.fileupload.IOUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.core.io.InputStreamResource;
    import org.springframework.web.bind.annotation.*;
    import org.springframework.web.multipart.MultipartFile;
    
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.URLConnection;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    import java.util.List;
    
    /**
     * @author zhan
     * @since 2020-05-18 14:50
     */
    @RestController
    public class TestController {
        @Autowired
        MinioService minioService;
    
        @Autowired
        private MinioConfigurationProperties configurationProperties;
    
        @GetMapping("/files")
        public List<Item> testMinio(){
            return minioService.list();
        }
    
        /**
         * 根据文件名称下载文件
         * @param object
         * @param response
         * @throws com.jlefebure.spring.boot.minio.MinioException
         * @throws IOException
         * @throws IOException
         */
        @GetMapping("files/{object}")
        public void getObject(@PathVariable("object") String object, HttpServletResponse response) throws com.jlefebure.spring.boot.minio.MinioException, IOException, IOException {
            InputStream inputStream = minioService.get(Paths.get(object));
            InputStreamResource inputStreamResource = new InputStreamResource(inputStream);
    
            // Set the content type and attachment header.
            response.addHeader("Content-disposition", "attachment;filename=" + object);
            response.setContentType(URLConnection.guessContentTypeFromName(object));
    
            // Copy the stream to the response's output stream.
            IOUtils.copy(inputStream, response.getOutputStream());
            response.flushBuffer();
        }
        @PostMapping("/upload")
        public void addAttachement(@RequestParam("file") MultipartFile file) throws IOException {
            System.out.println(file);
            String filename = file.getOriginalFilename();
            // System.out.println(filename);
            // Path path = Paths.get(file.getResource().getURI());
            Path path = Paths.get(filename);
            String url = configurationProperties.getUrl() + "/" + configurationProperties.getBucket() + path.toAbsolutePath();
            // System.out.println(path.toAbsolutePath());
            // url += path.toAbsolutePath();
            System.out.println(url);
            // System.out.println(path);
            try {
                minioService.upload(path, file.getInputStream(), file.getContentType());
                System.out.println("上传完成!!!");
            } catch (com.jlefebure.spring.boot.minio.MinioException e) {
                throw new IllegalStateException("The file cannot be upload on the internal storage. Please retry later", e);
            } catch (IOException e) {
                throw new IllegalStateException("The file cannot be read", e);
            }
        }
    }
        # 附上单元方法测试结论。
        @Test
        public void t1() throws IOException, InvalidKeyException, NoSuchAlgorithmException, InsufficientDataException, InvalidExpiresRangeException, InvalidResponseException, InternalException, NoResponseException, InvalidBucketNameException, XmlPullParserException, ErrorResponseException, BucketPolicyTooLargeException, InvalidObjectPrefixException {
            System.out.println(mmclient);
            Iterable<Result<Item>> results = mmclient.listObjects("gulimall");
            for (Result<Item> result : results) {
                Item item = result.get();
                System.out.println(item.lastModified() + ", " + item.size() + ", " + item.objectName());
            }
            //根据文件名称获取浏览地址,此种方式在不设置策略的情况下【使用默认策略】是不能直接下载文件的
            String gulimall = mmclient.presignedGetObject("gulimall", "11111.jpg");
            System.out.println("下载地址:"+gulimall);
            String gulimall1 = mmclient.getBucketLifeCycle("gulimall");
            System.out.println(gulimall1);// 空
            String policy = mmclient.getBucketPolicy("gulimall");
            System.out.println("policy:"+policy);
            //通过修改桶策略即可使用返回的url直接访问minio中的文件【推荐这种方式!!!】
            String objectUrl = mmclient.getObjectUrl("gulimall", "刘德华+-+练习.ape");
            System.out.println("objectUrl:" + objectUrl);
            //不能下载
            String putObject = mmclient.presignedPutObject("gulimall", "刘德华+-+练习.ape");
            System.out.println("putObject:"+putObject);
    
        }
    

    读写策略json如下【简单粗暴点也可在搭建完成后直接在控制台操作】:

    {
        "Version": "2012-10-17",
        "Statement": [{
            "Effect": "Allow",
            "Principal": {
                "AWS": ["*"]
            },
            "Action": ["s3:ListBucketMultipartUploads", "s3:GetBucketLocation", "s3:ListBucket"],
            "Resource": ["arn:aws:s3:::gulimall"]
        }, {
            "Effect": "Allow",
            "Principal": {
                "AWS": ["*"]
            },
            "Action": ["s3:AbortMultipartUpload", "s3:DeleteObject", "s3:GetObject", "s3:ListMultipartUploadParts", "s3:PutObject"],
            "Resource": ["arn:aws:s3:::gulimall/*"]
        }]
    }
    

    image-20200825175638426

    链接:https://www.jianshu.com/p/d81e9ecb4298

  • 相关阅读:
    BAT脚本编写要点(1)_特殊字符
    开源爬虫软件汇总
    使用Gradle发布项目到JCenter仓库
    解决Android中,禁止ScrollView内的控件改变之后自动滚动
    理解RESTful架构
    一种为 Apk 动态写入信息的方案
    Proguard配置注解
    使用statsvn统计svn中的代码量
    android如何释放图片缓存
    Git命令参考手册(文本版)
  • 原文地址:https://www.cnblogs.com/dalianpai/p/13561008.html
Copyright © 2011-2022 走看看