亚马逊网站建设进度计划书设迹官网
什么是minio
MinIO是一个基于Go实现的高性能、兼容S3协议的对象存储。它采用GNU AGPL v3开源协议,项目地址是https://github.com/minio/minio。
引用官网:
MinIO是根据GNU Affero通用公共许可证v3.0发布的高性能对象存储。它与Amazon S3云存储服务兼容。使用MinIO构建用于机器学习,分析和应用程序数据工作负载的高性能基础架构。
官网地址:
https://min.io/
文档地址:
https://docs.min.io/
一. 使用docker 搭建minio 服务
GNU / Linux和macOS
docker run -p 9000:9000 \   --name minio1 \   -v /mnt/data:/data \   -e "MINIO_ROOT_USER=AKIAIOSFODNN7EXAMPLE" \   -e "MINIO_ROOT_PASSWORD=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" \   minio/minio server /data 
windows
docker run -p 9000:9000 \   --name minio1 \   -v D:\data:/data \   -e "MINIO_ROOT_USER=AKIAIOSFODNN7EXAMPLE" \   -e "MINIO_ROOT_PASSWORD=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY" \   minio/minio server /data 
-  
MINIO_ROOT_USER:为用户key -  
MINIO_ROOT_PASSWORD:为用户密钥 
以上搭建的都是单机版的。想要了解分布式 的方式请查看官网文档。

这就是在win的docker上运行的。
更多开源项目:https://www.yoodb.com/projects/springboot-user-manger.html
当启动后在浏览器访问http://localhost:9000就可以访问minio的图形化界面了,如图所示:


二. 下面开始搭建springboot 环境
初始化一个springboot项目大家都会,这里不多做介绍。
主要是介绍需要引入的依赖:
<!-- thymeleaf模板渲染引擎-->  <dependency>            <groupId>org.springframework.boot</groupId>            <artifactId>spring-boot-starter-thymeleaf</artifactId>        </dependency><!-- 操作minio的java客户端-->         <dependency>            <groupId>io.minio</groupId>            <artifactId>minio</artifactId>            <version>8.2.1</version>        </dependency><!-- lombok插件-->         <dependency>            <groupId>org.projectlombok</groupId>            <artifactId>lombok</artifactId>            <optional>true</optional>        </dependency>
 
依赖可以官方文档里找:https://docs.min.io/docs/java-client-quickstart-guide.html
下面介绍配置文件:
spring:   servlet:     multipart:       max-file-size: 10MB       max-request-size: 10MB *#minio配置*   minio:     access-key: AKIAIOSFODNN7EXAMPLE      *#key就是docker初始化是设置的,密钥相同*     secret-key: wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY     url: http://localhost:9000     bucket-name: wdhcr   thymeleaf:     cache: false 
创建minio的配置类:
`@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 client对象放入容器中。
下面就是我封装的minio client 操作minio的简单方法的组件。
`@Component
 public class MinioComp {
@Autowired
     private MinioClient minioClient;
@Autowired
     private MinioConfiguration configuration;
/**
      * @description: 获取上传临时签名,公众 号Java精选
      * @dateTime: 2021/5/13 14:12
      */
     public Map getPolicy(String fileName, ZonedDateTime time) {
         PostPolicy postPolicy = new PostPolicy(configuration.getBucketName(), time);
         postPolicy.addEqualsCondition(“key”, fileName);
         try {
             Map<String, String> map = minioClient.getPresignedPostFormData(postPolicy);
             HashMap<String, String> map1 = new HashMap<>();
             map.forEach((k,v)->{
                map1.put(k.replaceAll(“-”,“”),v);
            });
             map1.put(“host”,configuration.getUrl()+“/”+configuration.getBucketName());
             return map1;
         } catch (ErrorResponseException e) {
             e.printStackTrace();
         } catch (InsufficientDataException e) {
             e.printStackTrace();
         } catch (InternalException e) {
             e.printStackTrace();
         } catch (InvalidKeyException e) {
             e.printStackTrace();
         } catch (InvalidResponseException e) {
             e.printStackTrace();
         } catch (IOException e) {
             e.printStackTrace();
         } catch (NoSuchAlgorithmException e) {
             e.printStackTrace();
         } catch (ServerException e) {
             e.printStackTrace();
         } catch (XmlParserException e) {
             e.printStackTrace();
         }
         return null;
     }
/**
      * @description: 获取上传文件的url,公众 号Java精选,有惊喜!
      * @dateTime: 2021/5/13 14:15
      */
     public String getPolicyUrl(String objectName, Method method, int time, TimeUnit timeUnit) {
         try {
             return minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
                     .method(method)
                     .bucket(configuration.getBucketName())
                     .object(objectName)
                     .expiry(time, timeUnit).build());
         } catch (ErrorResponseException e) {
             e.printStackTrace();
         } catch (InsufficientDataException e) {
             e.printStackTrace();
         } catch (InternalException e) {
             e.printStackTrace();
         } catch (InvalidKeyException e) {
             e.printStackTrace();
         } catch (InvalidResponseException e) {
             e.printStackTrace();
         } catch (IOException e) {
             e.printStackTrace();
         } catch (NoSuchAlgorithmException e) {
             e.printStackTrace();
         } catch (XmlParserException e) {
             e.printStackTrace();
         } catch (ServerException e) {
             e.printStackTrace();
         }
         return null;
     }
/**
      * @description: 上传文件
      * @dateTime: 2021/5/13 14:17
      /
     public void upload(MultipartFile file, String fileName) {
         // 使用putObject上传一个文件到存储桶中。
         try {
             InputStream inputStream = file.getInputStream();
             minioClient.putObject(PutObjectArgs.builder()
                     .bucket(configuration.getBucketName())
                     .object(fileName)
                     .stream(inputStream, file.getSize(), -1)
                     .contentType(file.getContentType())
                     .build());
         } catch (ErrorResponseException e) {
             e.printStackTrace();
         } catch (InsufficientDataException e) {
             e.printStackTrace();
         } catch (InternalException e) {
             e.printStackTrace();
         } catch (InvalidKeyException e) {
             e.printStackTrace();
         } catch (InvalidResponseException e) {
             e.printStackTrace();
         } catch (IOException e) {
             e.printStackTrace();
         } catch (NoSuchAlgorithmException e) {
             e.printStackTrace();
         } catch (ServerException e) {
             e.printStackTrace();
         } catch (XmlParserException e) {
             e.printStackTrace();
         }
     }
   /*
      * @description: 根据filename获取文件访问地址
      * @dateTime: 2021/5/17 11:28
      */
     public String getUrl(String objectName, int time, TimeUnit timeUnit) {
         String url = null;
         try {
             url = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
                     .method(Method.GET)
                     .bucket(configuration.getBucketName())
                     .object(objectName)
                     .expiry(time, timeUnit).build());
         } catch (ErrorResponseException e) {
             e.printStackTrace();
         } catch (InsufficientDataException e) {
             e.printStackTrace();
         } catch (InternalException e) {
             e.printStackTrace();
         } catch (InvalidKeyException e) {
             e.printStackTrace();
         } catch (InvalidResponseException e) {
             e.printStackTrace();
         } catch (IOException e) {
             e.printStackTrace();
         } catch (NoSuchAlgorithmException e) {
             e.printStackTrace();
         } catch (XmlParserException e) {
             e.printStackTrace();
         } catch (ServerException e) {
             e.printStackTrace();
         }
         return url;
     }
 }
 `
简单说明:
-  
使用MultipartFile接收前端文件流,再上传到minio。
 -  
构建一个formData的签名数据,给前端,让前端之前上传到minio。
 -  
构建一个可以上传的临时URL给前端,前端通过携带文件请求该URL进行上传。
 -  
使用filename请求服务端获取临时访问文件的URL。(最长时间为7 天,想要永久性访问,需要其他设置,这里不做说明。)
 -  
推荐,公众 号Java精选,回复java面试,获取面试资料,支持在线刷题。
 
下面展示页面html,使用的是VUE+element-ui进行渲染。
`
         
             
传统上传
前端formData直传
前端Url直传
uploadHandle(options) {
                 let {file} = options;
                 this.traditionPost(file);
             },
             traditionPost(file) {
                 _that = this
                 const form = new FormData();
                 form.append(“fileName”, file.name);
                 form.append(“file”, file);
                 this.axiosPost(“post”, “/upload”, form).then(function (res) {
                     if (res.status === 200) {
                         _that.imgUrl = res.data.data
                     } else {
                         alert(“上传失败!”)
                     }
                 })
             },
             getpolicy(file) {
                 _that = this
                 axios.get(‘policy?fileName=’ + file.name)
                     .then(function (response) {
                         let {xamzalgorithm, xamzcredential, policy, xamzsignature, xamzdate, host} = response.data.data;
                         let formData = new FormData();
                         formData.append(“key”, file.name);
                         formData.append(“x-amz-algorithm”, xamzalgorithm);  // 让服务端返回200,不设置则默认返回204。
                         formData.append(“x-amz-credential”, xamzcredential);
                         formData.append(“policy”, policy);
                         formData.append(“x-amz-signature”, xamzsignature);
                         formData.append(“x-amz-date”, xamzdate);
                         formData.append(“file”, file);
                         // 发送 POST 请求
                         _that.axiosPost(“post”, host, formData).then(function (res) {
                             if (res.status === 204) {
                                 axios.get(‘url?fileName=’ + file.name).then(function (res) {
                                     _that.directUrl = res.data.data;
                                 })
                             } else {
                                 alert(“上传失败!”)
                             }
                         })
                     })
             },
             httpRequestHandle(options) {
                 let {file} = options;
                 this.getpolicy(file);
             },
UrlUploadHandle(options) {
                 let {file} = options;
                 this.getUploadUrl(file);
             },
             getUploadUrl(file) {
                 _that = this
                 console.log(file)
                 axios.get(‘uploadUrl?fileName=’ + file.name)
                     .then(function (response) {
                         let url = response.data.data;
                         // 发送 put 请求
                         let config = {‘Content-Type’: file.type}
                         _that.axiosPost(“put”, url, file, config).then(function (res) {
                             if (res.status === 200) {
                                 axios.get(‘url?fileName=’ + file.name).then(function (res) {
                                     _that.uploadUrl = res.data.data;
                                 })
                             } else {
                                 alert(“上传失败!”)
                             }
                         })
                     })
             },
             //封装
             //axios封装post请求
             axiosPost(method, url, data, config) {
                 let result = axios({
                     method: method,
                     url: url,
                     data: data,
                     headers: config
                 }).then(resp => {
                     return resp
                 }).catch(error => {
                     return “exception=” + error;
                 });
                 return result;
             }
}
     })
 

页面的效果就如上图所示。
可以分别体验不同的实现效果。
以上就是使用springboot搭建基于minio的高性能存储服务的全部步骤了。
本项目地址:
https://gitee.com/jack_whh/minio-upload
作者:HUWD
https://blog.csdn.net/weixin_45089791/article/details/116921075/
