Browse Source

1、minio实现文件上传与下载。

guanzi 4 years ago
parent
commit
fc3f44054a
19 changed files with 1020 additions and 479 deletions
  1. 1 1
      saas-backen/src/main/java/com/pavis/app/saasbacken/aop/SystemLogAspect.java
  2. 8 0
      saas-backen/src/main/java/com/pavis/app/saasbacken/config/MinioConfig.java
  3. 6 1
      saas-backen/src/main/java/com/pavis/app/saasbacken/controller/MinioController.java
  4. 17 0
      saas-backen/src/main/java/com/pavis/app/saasbacken/dao/CheckModuleMapper.java
  5. 17 0
      saas-backen/src/main/java/com/pavis/app/saasbacken/dao/InitDataChildMapper.java
  6. 17 0
      saas-backen/src/main/java/com/pavis/app/saasbacken/dao/InitDataParentMapper.java
  7. 17 0
      saas-backen/src/main/java/com/pavis/app/saasbacken/dao/InitDataThirdMapper.java
  8. 119 0
      saas-backen/src/main/java/com/pavis/app/saasbacken/entity/CheckModule.java
  9. 109 0
      saas-backen/src/main/java/com/pavis/app/saasbacken/entity/InitDataChild.java
  10. 106 0
      saas-backen/src/main/java/com/pavis/app/saasbacken/entity/InitDataParent.java
  11. 109 0
      saas-backen/src/main/java/com/pavis/app/saasbacken/entity/InitDataThird.java
  12. 2 2
      saas-backen/src/main/java/com/pavis/app/saasbacken/exception/OrgException.java
  13. 1 0
      saas-backen/src/main/java/com/pavis/app/saasbacken/http/ErrorCode.java
  14. 38 0
      saas-backen/src/main/java/com/pavis/app/saasbacken/service/MinioService.java
  15. 2 2
      saas-backen/src/main/java/com/pavis/app/saasbacken/service/impl/base/DicServiceImpl.java
  16. 145 7
      saas-backen/src/main/java/com/pavis/app/saasbacken/service/impl/other/MinioServiceImpl.java
  17. 298 465
      saas-backen/src/main/java/com/pavis/app/saasbacken/utils/MinioUtils.java
  18. 6 0
      saas-backen/src/main/resources/application-dev.yml
  19. 2 1
      saas-backen/src/main/resources/error.properties

+ 1 - 1
saas-backen/src/main/java/com/pavis/app/saasbacken/aop/SystemLogAspect.java

@@ -106,7 +106,7 @@ public class SystemLogAspect {
             String operateTime = DateUtils.getCurrentTime();
             String param = list.toString();
 
-            log.info("\nurl:{}\nusername:{}\ndatetime:{}\nrequestMethod:{}\naction:{}\nmethod:{}\nparam:{}\nresponse:{}\nresult:{}\ntime:{}ms", url,
+            log.info("\nurl:{}\nusername:{}\ndatetime:{}\nrequestMethod:{}\naction:{}()\nmethod:{}\nparam:{}\nresponse:{}\nresult:{}\ntime:{}ms", url,
                     "username", operateTime,controllerName,action,opName, param, JSON.toJSONString(jsonSet),resParam, time);
 
             OperateLog operateLog = OperateLog.builder()

+ 8 - 0
saas-backen/src/main/java/com/pavis/app/saasbacken/config/MinioConfig.java

@@ -50,6 +50,14 @@ public class MinioConfig {
     @Value("${spring.minio.configDir}")
     private String configDir;
 
+    @ApiModelProperty("文件大小")
+    @Value("${spring.minio.maxFileSize}")
+    private Integer maxFileSize;
+
+    @ApiModelProperty("签名有效时间")
+    @Value("${spring.minio.expires}")
+    private Integer expires;
+
     // @Bean
     // public MinioClient getMinioClient() throws InvalidEndpointException, InvalidPortException {
     //     log.info("endpoint:{},port:{},accessKey:{},secretKey:{},secure:{}",endpoint, port, accessKey, secretKey,secure);

+ 6 - 1
saas-backen/src/main/java/com/pavis/app/saasbacken/controller/MinioController.java

@@ -59,7 +59,12 @@ public class MinioController {
      * @param filename
      */
     @GetMapping("/download/{filename}")
-    public void download(@PathVariable String filename, HttpServletResponse res) throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, ErrorResponseException {
+    public void download(@PathVariable String filename, HttpServletResponse res) throws Exception {
+
+        minioService.presignedGetObject("push-test",filename,null);
+        log.info("start download....:{}",filename);
+        minioService.setFile();
+        minioService.getSignedUrl(filename);
         minioService.download(filename,res);
     }
 

+ 17 - 0
saas-backen/src/main/java/com/pavis/app/saasbacken/dao/CheckModuleMapper.java

@@ -0,0 +1,17 @@
+package com.pavis.app.saasbacken.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.pavis.app.saasbacken.entity.CheckModule;
+import org.springframework.stereotype.Component;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author guan
+ * @since 2021-10-29
+ */
+@Component
+public interface CheckModuleMapper extends BaseMapper<CheckModule> {
+}

+ 17 - 0
saas-backen/src/main/java/com/pavis/app/saasbacken/dao/InitDataChildMapper.java

@@ -0,0 +1,17 @@
+package com.pavis.app.saasbacken.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.pavis.app.saasbacken.entity.InitDataChild;
+import org.springframework.stereotype.Component;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author guan
+ * @since 2021-10-29
+ */
+@Component
+public interface InitDataChildMapper extends BaseMapper<InitDataChild> {
+}

+ 17 - 0
saas-backen/src/main/java/com/pavis/app/saasbacken/dao/InitDataParentMapper.java

@@ -0,0 +1,17 @@
+package com.pavis.app.saasbacken.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.pavis.app.saasbacken.entity.InitDataParent;
+import org.springframework.stereotype.Component;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author guan
+ * @since 2021-10-29
+ */
+@Component
+public interface InitDataParentMapper extends BaseMapper<InitDataParent> {
+}

+ 17 - 0
saas-backen/src/main/java/com/pavis/app/saasbacken/dao/InitDataThirdMapper.java

@@ -0,0 +1,17 @@
+package com.pavis.app.saasbacken.dao;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.pavis.app.saasbacken.entity.InitDataThird;
+import org.springframework.stereotype.Component;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author guan
+ * @since 2021-10-29
+ */
+@Component
+public interface InitDataThirdMapper extends BaseMapper<InitDataThird> {
+}

+ 119 - 0
saas-backen/src/main/java/com/pavis/app/saasbacken/entity/CheckModule.java

@@ -0,0 +1,119 @@
+package com.pavis.app.saasbacken.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Builder;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+
+/**
+ * <p>
+ * 所选功能关联关系表
+ * </p>
+ *
+ * @author guan
+ * @since 2021-10-29
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@TableName("check_module")
+@ApiModel(value="CheckModule对象", description="")
+@Builder
+public class CheckModule extends Model<CheckModule> {
+
+    @ApiModelProperty(value = "主键自增id")
+    // @TableId(value = "id", type = IdType.INPUT)
+    @TableId(type = IdType.ASSIGN_UUID)
+    private String id;
+
+    @ApiModelProperty(value = "资源库代码")
+    private String resType;
+
+    @ApiModelProperty(value = "功能名称")
+    private String title;
+
+    @ApiModelProperty(value = "功能名称代码")
+    private String titleCode;
+
+    @ApiModelProperty(value = "上级节点id")
+    private String parentId;
+
+    @ApiModelProperty(value = "图标")
+    private String icon;
+
+    @ApiModelProperty(value = "是否可用")
+    private String isEnabled;
+
+    @ApiModelProperty(value = "是否必填")
+    private String isMust;
+
+    @ApiModelProperty(value = "是否排序")
+    private String isSorted;
+
+    @ApiModelProperty(value = "单选:是/否,是否有二级目录")
+    private String weatherChild;
+
+    // input()、单选框、复选框、下拉选择、图片、是/否、是/否二级目录、
+    @ApiModelProperty(value = "前端展示类型")
+    private String showType;
+
+    @ApiModelProperty(value = "备注")
+    private String remark;
+
+    @ApiModelProperty(value = "预留字段1")
+    private String by1;
+
+    @ApiModelProperty(value = "预留字段2")
+    private String by2;
+
+    @ApiModelProperty(value = "预留字段3")
+    private String by3;
+
+    @ApiModelProperty(value = "预留字段4")
+    private String by4;
+
+    @ApiModelProperty(value = "预留字段5")
+    private String by5;
+
+    @ApiModelProperty(value = "预留字段6")
+    private String by6;
+
+    @ApiModelProperty(value = "预留字段7")
+    private String by7;
+
+    @ApiModelProperty(value = "预留字段8")
+    private String by8;
+
+    @ApiModelProperty(value = "预留字段9")
+    private String by9;
+
+    @ApiModelProperty(value = "预留字段10")
+    private String by10;
+
+    @ApiModelProperty(value = "创建时间")
+    private String createTime;
+
+    @ApiModelProperty(value = "创建者")
+    private Long creator;
+
+    @ApiModelProperty(value = "更新时间")
+    private String updateTime;
+
+    @ApiModelProperty(value = "更新者")
+    private Long updator;
+
+
+    @Override
+    protected Serializable pkVal() {
+        return this.id;
+    }
+
+}

+ 109 - 0
saas-backen/src/main/java/com/pavis/app/saasbacken/entity/InitDataChild.java

@@ -0,0 +1,109 @@
+package com.pavis.app.saasbacken.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Builder;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+
+/**
+ * <p>
+ * 初始化data2
+ * </p>
+ *
+ * @author guan
+ * @since 2021-10-29
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@TableName("init_data_child")
+@ApiModel(value="InitDataChild对象", description="")
+@Builder
+public class InitDataChild extends Model<InitDataChild> {
+
+    @ApiModelProperty(value = "主键自增id")
+    // @TableId(value = "id", type = IdType.INPUT)
+    @TableId(type = IdType.ASSIGN_UUID)
+    private String id;
+
+    @ApiModelProperty(value = "初始化数据父级代码")
+    private String initCode;
+
+    @ApiModelProperty(value = "初始化数据父级名称")
+    private String title;
+
+    @ApiModelProperty(value = "父级名称代码")
+    private String titleCode;
+
+    @ApiModelProperty(value = "是否含有子级")
+    private String isChild;
+
+    @ApiModelProperty(value = "上级节点id")
+    private String parentId;
+
+    @ApiModelProperty(value = "图标")
+    private String icon;
+
+    @ApiModelProperty(value = "是否可用")
+    private String isEnabled;
+
+    @ApiModelProperty(value = "备注")
+    private String remark;
+
+    @ApiModelProperty(value = "预留字段1")
+    private String by1;
+
+    @ApiModelProperty(value = "预留字段2")
+    private String by2;
+
+    @ApiModelProperty(value = "预留字段3")
+    private String by3;
+
+    @ApiModelProperty(value = "预留字段4")
+    private String by4;
+
+    @ApiModelProperty(value = "预留字段5")
+    private String by5;
+
+    @ApiModelProperty(value = "预留字段6")
+    private String by6;
+
+    @ApiModelProperty(value = "预留字段7")
+    private String by7;
+
+    @ApiModelProperty(value = "预留字段8")
+    private String by8;
+
+    @ApiModelProperty(value = "预留字段9")
+    private String by9;
+
+    @ApiModelProperty(value = "预留字段10")
+    private String by10;
+
+    @ApiModelProperty(value = "创建时间")
+    private String createTime;
+
+    @ApiModelProperty(value = "创建者")
+    private Long creator;
+
+    @ApiModelProperty(value = "更新时间")
+    private String updateTime;
+
+    @ApiModelProperty(value = "更新者")
+    private Long updator;
+
+
+    @Override
+    protected Serializable pkVal() {
+        return this.id;
+    }
+
+}

+ 106 - 0
saas-backen/src/main/java/com/pavis/app/saasbacken/entity/InitDataParent.java

@@ -0,0 +1,106 @@
+package com.pavis.app.saasbacken.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Builder;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+
+/**
+ * <p>
+ * 初始化data1
+ * </p>
+ *
+ * @author guan
+ * @since 2021-10-29
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@TableName("init_data_parent")
+@ApiModel(value="InitDataParent对象", description="")
+@Builder
+public class InitDataParent extends Model<InitDataParent> {
+
+    @ApiModelProperty(value = "主键自增id")
+    // @TableId(value = "id", type = IdType.INPUT)
+    @TableId(type = IdType.ASSIGN_UUID)
+    private String id;
+
+    @ApiModelProperty(value = "初始化数据父级代码")
+    private String initCode;
+
+    @ApiModelProperty(value = "初始化数据父级名称")
+    private String title;
+
+    @ApiModelProperty(value = "父级名称代码")
+    private String titleCode;
+
+    @ApiModelProperty(value = "是否含有子级")
+    private String isChild;
+
+    @ApiModelProperty(value = "图标")
+    private String icon;
+
+    @ApiModelProperty(value = "是否可用")
+    private String isEnabled;
+
+    @ApiModelProperty(value = "备注")
+    private String remark;
+
+    @ApiModelProperty(value = "预留字段1")
+    private String by1;
+
+    @ApiModelProperty(value = "预留字段2")
+    private String by2;
+
+    @ApiModelProperty(value = "预留字段3")
+    private String by3;
+
+    @ApiModelProperty(value = "预留字段4")
+    private String by4;
+
+    @ApiModelProperty(value = "预留字段5")
+    private String by5;
+
+    @ApiModelProperty(value = "预留字段6")
+    private String by6;
+
+    @ApiModelProperty(value = "预留字段7")
+    private String by7;
+
+    @ApiModelProperty(value = "预留字段8")
+    private String by8;
+
+    @ApiModelProperty(value = "预留字段9")
+    private String by9;
+
+    @ApiModelProperty(value = "预留字段10")
+    private String by10;
+
+    @ApiModelProperty(value = "创建时间")
+    private String createTime;
+
+    @ApiModelProperty(value = "创建者")
+    private Long creator;
+
+    @ApiModelProperty(value = "更新时间")
+    private String updateTime;
+
+    @ApiModelProperty(value = "更新者")
+    private Long updator;
+
+
+    @Override
+    protected Serializable pkVal() {
+        return this.id;
+    }
+
+}

+ 109 - 0
saas-backen/src/main/java/com/pavis/app/saasbacken/entity/InitDataThird.java

@@ -0,0 +1,109 @@
+package com.pavis.app.saasbacken.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.baomidou.mybatisplus.extension.activerecord.Model;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Builder;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.experimental.Accessors;
+
+import java.io.Serializable;
+
+/**
+ * <p>
+ * 初始化data3
+ * </p>
+ *
+ * @author guan
+ * @since 2021-10-29
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@Accessors(chain = true)
+@TableName("init_data_third")
+@ApiModel(value="InitDataThird对象", description="")
+@Builder
+public class InitDataThird extends Model<InitDataThird> {
+
+    @ApiModelProperty(value = "主键自增id")
+    // @TableId(value = "id", type = IdType.INPUT)
+    @TableId(type = IdType.ASSIGN_UUID)
+    private String id;
+
+    @ApiModelProperty(value = "初始化数据父级代码")
+    private String initCode;
+
+    @ApiModelProperty(value = "初始化数据父级名称")
+    private String title;
+
+    @ApiModelProperty(value = "父级名称代码")
+    private String titleCode;
+
+    @ApiModelProperty(value = "是否含有子级")
+    private String isChild;
+
+    @ApiModelProperty(value = "上级节点id")
+    private String parentId;
+
+    @ApiModelProperty(value = "图标")
+    private String icon;
+
+    @ApiModelProperty(value = "是否可用")
+    private String isEnabled;
+
+    @ApiModelProperty(value = "备注")
+    private String remark;
+
+    @ApiModelProperty(value = "预留字段1")
+    private String by1;
+
+    @ApiModelProperty(value = "预留字段2")
+    private String by2;
+
+    @ApiModelProperty(value = "预留字段3")
+    private String by3;
+
+    @ApiModelProperty(value = "预留字段4")
+    private String by4;
+
+    @ApiModelProperty(value = "预留字段5")
+    private String by5;
+
+    @ApiModelProperty(value = "预留字段6")
+    private String by6;
+
+    @ApiModelProperty(value = "预留字段7")
+    private String by7;
+
+    @ApiModelProperty(value = "预留字段8")
+    private String by8;
+
+    @ApiModelProperty(value = "预留字段9")
+    private String by9;
+
+    @ApiModelProperty(value = "预留字段10")
+    private String by10;
+
+    @ApiModelProperty(value = "创建时间")
+    private String createTime;
+
+    @ApiModelProperty(value = "创建者")
+    private Long creator;
+
+    @ApiModelProperty(value = "更新时间")
+    private String updateTime;
+
+    @ApiModelProperty(value = "更新者")
+    private Long updator;
+
+
+    @Override
+    protected Serializable pkVal() {
+        return this.id;
+    }
+
+}

+ 2 - 2
saas-backen/src/main/java/com/pavis/app/saasbacken/exception/OrgException.java

@@ -6,11 +6,11 @@ import com.pavis.app.saasbacken.http.ErrorCode;
 public class OrgException extends BaseException {
 
     public OrgException() {
-        this(ErrorCode.ACCOUNT_EXPIRED.getCode(), ErrorCode.ACCOUNT_EXPIRED.getMessage());
+        this(ErrorCode.FILENAME_NULL.getCode(), ErrorCode.FILENAME_NULL.getMessage());
     }
 
     public OrgException(String msg) {
-        this(ErrorCode.ACCOUNT_EXPIRED.getCode(), msg);
+        this(ErrorCode.FILENAME_NULL.getCode(), msg);
     }
 
     public OrgException(int code, String msg) {

+ 1 - 0
saas-backen/src/main/java/com/pavis/app/saasbacken/http/ErrorCode.java

@@ -42,6 +42,7 @@ public enum ErrorCode {
 
     QA_NO_RESPONSE(4032, "qa_no_response"),
     ILLEGAL_ARGUMENT(4034, "illegal_argument"),
+    FILENAME_NULL(4035,"filename_null"),
 
 
     /**

+ 38 - 0
saas-backen/src/main/java/com/pavis/app/saasbacken/service/MinioService.java

@@ -32,4 +32,42 @@ public interface MinioService {
      * @param res
      */
     void download(@PathVariable String filename, HttpServletResponse res) throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, ErrorResponseException;
+
+    /**
+     * 获取文件url。
+     * @param bucketName
+     * @param objectName
+     * @param expires
+     * @return
+     */
+    String presignedGetObject(String bucketName, String objectName, Integer expires) throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, ErrorResponseException;
+
+    /**
+     * 校验存储桶是否存在。
+     * @param bucketName
+     * @return
+     */
+    Boolean checkBucket(String bucketName) throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, ErrorResponseException;
+
+    /**
+     * 存储桶不存在,新建存储桶。
+     * @param bucketName
+     * @return
+     */
+    Map<String,Object> makeBucket(String bucketName) throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, ErrorResponseException;
+
+    /**
+     * 返回文件url前缀。
+     * @return
+     * @throws Exception
+     */
+    String setFile() throws Exception;
+
+    /**
+     * 返回签名的url。
+     * @param fileName
+     * @return
+     * @throws Exception
+     */
+    String getSignedUrl(String fileName) throws Exception;
 }

+ 2 - 2
saas-backen/src/main/java/com/pavis/app/saasbacken/service/impl/base/DicServiceImpl.java

@@ -39,8 +39,8 @@ public class DicServiceImpl extends ServiceImpl<DicMapper, Dic> implements DicSe
         // 资源库目录
         dics.add(initDic("6","企业库","enterpriseInfo",
                 "0","url","0"));
-        // dics.add(initDic("1","需求库","xuqiu",
-        //         "0","url","0"));
+        dics.add(initDic("1","需求库","xuqiu",
+                "0","url","0"));
         // dics.add(initDic("2","成果库","",
         //         "0","url","0"));
         // dics.add(initDic("8","专家库","",

+ 145 - 7
saas-backen/src/main/java/com/pavis/app/saasbacken/service/impl/other/MinioServiceImpl.java

@@ -1,11 +1,17 @@
 package com.pavis.app.saasbacken.service.impl.other;
 
 
+import com.alibaba.fastjson.JSON;
+import com.pavis.app.saasbacken.exception.OrgException;
+import com.pavis.app.saasbacken.http.ErrorCode;
 import com.pavis.app.saasbacken.service.MinioService;
+import com.pavis.app.saasbacken.utils.MinioUtils;
 import io.minio.*;
 import io.minio.errors.*;
+import io.minio.http.Method;
 import io.minio.messages.Bucket;
 import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 import org.springframework.util.FastByteArrayOutputStream;
@@ -35,6 +41,9 @@ public class MinioServiceImpl implements MinioService {
     @Value("${spring.minio.bucketName}")
     private String bucketName;
 
+    @Value("${spring.minio.expires}")
+    private Integer expires;
+
     @Resource
     private MinioClient minioClient;
 
@@ -77,21 +86,16 @@ public class MinioServiceImpl implements MinioService {
 
         GetObjectArgs objectArgs = GetObjectArgs.builder().bucket(bucketName)
                 .object(filename).build();
-
+        System.err.println("objectArgs:" + JSON.toJSONString(objectArgs));
         try (GetObjectResponse response = minioClient.getObject(objectArgs)) {
+            System.err.println("response:" + JSON.toJSONString(response));
             byte[] buf = new byte[1024];
-
             int len;
-
             try (FastByteArrayOutputStream os = new FastByteArrayOutputStream()) {
-
                 while ((len = response.read(buf)) != -1) {
-
                     os.write(buf, 0, len);
-
                 }
                 os.flush();
-
                 byte[] bytes = os.toByteArray();
 
                 res.setCharacterEncoding("utf-8");
@@ -106,5 +110,139 @@ public class MinioServiceImpl implements MinioService {
         } catch (Exception e) {
             e.printStackTrace();
         }
+
+        // try {
+        //     // 调用statObject()来判断对象是否存在。
+        //     // 如果不存在, statObject()抛出异常,
+        //     // 否则则代表对象存在。
+        //     minioClient.statObject("mybucket", "myobject");
+        //
+        //     // 获取myobject的流并保存到photo.jpg文件中。
+        //     minioClient.getObject("mybucket", "myobject", "photo.jpg");
+        //
+        // } catch (MinioException e) {
+        //     System.out.println("Error occurred: " + e);
+        // }
+    }
+
+    /**
+     * 生成一个GET请求的分享链接。
+     * 失效时间默认是7天。
+     *
+     * @param bucketName 存储桶名称
+     * @param objectName 存储桶里的对象名称
+     * @param expires    失效时间(以秒为单位),默认是7天,不得大于七天
+     * @return
+     */
+    public String presignedGetObject(String bucketName, String objectName, Integer expires) throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, ErrorResponseException {
+        BucketExistsArgs bucketArgs = BucketExistsArgs.builder().bucket(bucketName).build();
+        boolean bucketExists = minioClient.bucketExists(bucketArgs);
+        // boolean flag = bucketExists(bucketName);
+        String url = "";
+        if (bucketExists) {
+            try {
+                if (expires == null){
+                    expires = 604800;
+                }
+
+                GetPresignedObjectUrlArgs getPresignedObjectUrlArgs = GetPresignedObjectUrlArgs.builder()
+                        .method(Method.GET)
+                        .bucket(bucketName)
+                        .object(objectName)
+                        // .expiry(expires)
+                        .build();
+                url = minioClient.getPresignedObjectUrl(getPresignedObjectUrlArgs);
+                log.info("*******url2:{}",url);
+                // url = minioClient.presignedGetObject(bucketName, objectName, expires);
+            } catch (Exception e) {
+                log.info("presigned get object fail:{}",e);
+            }
+        }
+        return url;
+    }
+
+    /**
+     * 校验存储桶。
+     * @param bucketName
+     * @return
+     */
+    public Boolean checkBucket(String bucketName) throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, ErrorResponseException {
+        BucketExistsArgs bucketArgs = BucketExistsArgs.builder().bucket(bucketName).build();
+        return minioClient.bucketExists(bucketArgs);
+    }
+
+    /**
+     * 存储桶不存在,新建存储桶。
+     * @param bucketName
+     * @return
+     */
+    public Map<String,Object> makeBucket(String bucketName) throws IOException, InvalidKeyException, InvalidResponseException, InsufficientDataException, NoSuchAlgorithmException, ServerException, InternalException, XmlParserException, ErrorResponseException {
+        BucketExistsArgs bucketArgs = BucketExistsArgs.builder().bucket(bucketName).build();
+        boolean bucketExists = minioClient.bucketExists(bucketArgs);
+        Map<String,Object> makeMap = new HashMap<>();
+        if (!bucketExists){
+            // 存储桶不存在,并且需要创建存储桶
+            minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
+            boolean makeBucketExists = minioClient.bucketExists(bucketArgs);
+            if (true == makeBucketExists){
+                makeMap.put("code","1");
+                makeMap.put("mes","创建成功");
+                return makeMap;
+            }else {
+                makeMap.put("code","0");
+                makeMap.put("mes","创建失败");
+                return makeMap;
+            }
+        }else {
+            makeMap.put("code","-1");
+            makeMap.put("mes","存储桶已存在,无需创建。");
+            return makeMap;
+        }
+    }
+
+    /**
+     * 获取文件签名url
+     *
+     * @param fileName 文件名称
+     * @return 文件签名地址
+     */
+    public String getSignedUrl(String fileName) throws Exception {
+        if (StringUtils.isBlank(fileName)) {
+            throw new OrgException(ErrorCode.FILENAME_NULL.getCode(),ErrorCode.FILENAME_NULL.getMessage());
+        }
+        String presignedObjectUrl = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
+                .method(Method.GET)
+                .bucket(bucketName)
+                .object(getFileName(fileName))
+                .expiry(expires).build());
+        System.err.println("presignedObjectUrl:" + presignedObjectUrl);
+        return presignedObjectUrl;
     }
+
+    /**
+     * 返回文件URL
+     *
+     * @return
+     */
+    public String setFile() throws Exception {
+        String objectPrefixUrl = MinioUtils.getObjectPrefixUrl(bucketName);
+        log.info("objectPrefixUrl:{}",objectPrefixUrl);
+        return objectPrefixUrl;
+    }
+
+
+    /**
+     * 处理文件名称(当fileName 不是文件名称为文件存储路径地址时)
+     *
+     * @return
+     */
+    private static String getFileName(String fileName) {
+        if (fileName.contains("/")) {
+            String[] split = fileName.split("/");
+            return split[split.length - 1];
+        } else {
+            return fileName;
+        }
+    }
+
 }

+ 298 - 465
saas-backen/src/main/java/com/pavis/app/saasbacken/utils/MinioUtils.java

@@ -1,465 +1,298 @@
-// package com.pavis.app.saasbacken.utils;
-//
-// import com.pavis.app.saasbacken.config.MinioConfig;
-// import io.minio.MinioClient;
-// import io.minio.ObjectStat;
-// import io.minio.PutObjectOptions;
-// import io.minio.Result;
-// import io.minio.errors.ErrorResponseException;
-// import io.minio.errors.InvalidExpiresRangeException;
-// import io.minio.messages.Bucket;
-// import io.minio.messages.DeleteError;
-// import io.minio.messages.Item;
-// import lombok.SneakyThrows;
-// import lombok.extern.slf4j.Slf4j;
-// import org.apache.commons.lang3.StringUtils;
-// import org.springframework.beans.factory.annotation.Autowired;
-// import org.springframework.stereotype.Component;
-// import org.springframework.web.multipart.MultipartFile;
-//
-// import javax.annotation.PostConstruct;
-// import javax.annotation.Resource;
-// import javax.servlet.ServletOutputStream;
-// import javax.servlet.http.HttpServletResponse;
-// import java.io.InputStream;
-// import java.nio.charset.StandardCharsets;
-// import java.util.ArrayList;
-// import java.util.List;
-//
-// /**
-//  * @program: push-saas
-//  * @description:
-//  * @author: Guanzi
-//  * @created: 2021/11/02 13:33
-//  */
-// @Slf4j
-// @Component
-// public class MinioUtils {
-//
-//     @Autowired
-//     private MinioClient minioClient;
-//
-//
-//
-//     private static final int DEFAULT_EXPIRY_TIME = 7 * 24 * 3600;
-//
-//     @Resource
-//     private MinioConfig minioConfig ;
-//
-//
-//     //
-//     // /**
-//     //  * 初始化 MinIO 客户端
-//     //  */
-//     // @PostConstruct
-//     // private void init(){
-//     //     try {
-//     //         minioClient = new MinioClient(minioConfig.getEndpoint(),
-//     //                 minioConfig.getAccessKey(),
-//     //                 minioConfig.getSecretKey());
-//     //     } catch (Exception e) {
-//     //         e.printStackTrace();
-//     //         log.info("MinIoClient init fail ...");
-//     //     }
-//     // }
-//
-//     // /**
-//     //  * 上传 <html> 页面
-//     //  */
-//     // public String uploadHtml (String fileName, String filePath) throws Exception {
-//     //     minioClient.putObject(minioConfig.getBucketName(),fileName,filePath);
-//     //     return minioConfig.getEndpoint()+"/"+minioConfig.getBucketName()+"/"+fileName ;
-//     // }
-//     //
-//     // /**
-//     //  * 上传 <img> 图片
-//     //  */
-//     // public String uploadImg (String imgName, String imgPath) throws Exception {
-//     //     minioClient.putObject(minioConfig.getBucketName(),imgName,imgPath);
-//     //     return minioConfig.getEndpoint()+"/"+minioConfig.getBucketName()+"/"+imgName ;
-//     // }
-//
-//     /**
-//      * 检查存储桶是否存在
-//      *
-//      * @param bucketName 存储桶名称
-//      * @return
-//      */
-//     @SneakyThrows
-//     public boolean bucketExists(String bucketName) {
-//         boolean flag = false;
-//         flag = minioClient.bucketExists(bucketName);
-//         if (flag) {
-//             return true;
-//         }
-//         return false;
-//     }
-//
-//     /**
-//      * 创建存储桶
-//      *
-//      * @param bucketName 存储桶名称
-//      */
-//     @SneakyThrows
-//     public boolean makeBucket(String bucketName) {
-//         boolean flag = bucketExists(bucketName);
-//         if (!flag) {
-//             minioClient.makeBucket(bucketName);
-//             return true;
-//         } else {
-//             return false;
-//         }
-//     }
-//
-//     /**
-//      * 列出所有存储桶名称
-//      *
-//      * @return
-//      */
-//     @SneakyThrows
-//     public List<String> listBucketNames() {
-//         List<Bucket> bucketList = listBuckets();
-//         List<String> bucketListName = new ArrayList<>();
-//         for (Bucket bucket : bucketList) {
-//             bucketListName.add(bucket.name());
-//         }
-//         return bucketListName;
-//     }
-//
-//     /**
-//      * 列出所有存储桶
-//      *
-//      * @return
-//      */
-//     @SneakyThrows
-//     public List<Bucket> listBuckets() {
-//         return minioClient.listBuckets();
-//     }
-//
-//     /**
-//      * 删除存储桶
-//      *
-//      * @param bucketName 存储桶名称
-//      * @return
-//      */
-//     @SneakyThrows
-//     public boolean removeBucket(String bucketName) {
-//         boolean flag = bucketExists(bucketName);
-//         if (flag) {
-//             Iterable<Result<Item>> myObjects = listObjects(bucketName);
-//             for (Result<Item> result : myObjects) {
-//                 Item item = result.get();
-//                 // 有对象文件,则删除失败
-//                 if (item.size() > 0) {
-//                     return false;
-//                 }
-//             }
-//             // 删除存储桶,注意,只有存储桶为空时才能删除成功。
-//             minioClient.removeBucket(bucketName);
-//             flag = bucketExists(bucketName);
-//             if (!flag) {
-//                 return true;
-//             }
-//
-//         }
-//         return false;
-//     }
-//
-//     /**
-//      * 列出存储桶中的所有对象名称
-//      *
-//      * @param bucketName 存储桶名称
-//      * @return
-//      */
-//     @SneakyThrows
-//     public List<String> listObjectNames(String bucketName) {
-//         List<String> listObjectNames = new ArrayList<>();
-//         boolean flag = bucketExists(bucketName);
-//         if (flag) {
-//             Iterable<Result<Item>> myObjects = listObjects(bucketName);
-//             for (Result<Item> result : myObjects) {
-//                 Item item = result.get();
-//                 listObjectNames.add(item.objectName());
-//             }
-//         }
-//         return listObjectNames;
-//     }
-//
-//     /**
-//      * 列出存储桶中的所有对象
-//      *
-//      * @param bucketName 存储桶名称
-//      * @return
-//      */
-//     @SneakyThrows
-//     public Iterable<Result<Item>> listObjects(String bucketName) {
-//         boolean flag = bucketExists(bucketName);
-//         if (flag) {
-//             return minioClient.listObjects(bucketName);
-//         }
-//         return null;
-//     }
-//
-//     /**
-//      * 通过文件上传到对象
-//      *
-//      * @param bucketName 存储桶名称
-//      * @param objectName 存储桶里的对象名称
-//      * @param fileName   File name
-//      * @return
-//      */
-//     @SneakyThrows
-//     public boolean putObject(String bucketName, String objectName, String fileName) {
-//         boolean flag = bucketExists(bucketName);
-//         if (flag) {
-//             minioClient.putObject(bucketName, objectName, fileName, null);
-//             ObjectStat statObject = statObject(bucketName, objectName);
-//             if (statObject != null && statObject.length() > 0) {
-//                 return true;
-//             }
-//         }
-//         return false;
-//
-//     }
-//
-//     /**
-//      * 文件上传
-//      *
-//      * @param bucketName
-//      * @param multipartFile
-//      */
-//     @SneakyThrows
-//     public void putObject(String bucketName, MultipartFile multipartFile, String filename) {
-//         PutObjectOptions putObjectOptions = new PutObjectOptions(multipartFile.getSize(), PutObjectOptions.MIN_MULTIPART_SIZE);
-//         putObjectOptions.setContentType(multipartFile.getContentType());
-//         minioClient.putObject(bucketName, filename, multipartFile.getInputStream(), putObjectOptions);
-//     }
-//
-//     /**
-//      * 通过InputStream上传对象
-//      *
-//      * @param bucketName 存储桶名称
-//      * @param objectName 存储桶里的对象名称
-//      * @param stream     要上传的流
-//      * @return
-//      */
-//     @SneakyThrows
-//     public boolean putObject(String bucketName, String objectName, InputStream stream) {
-//         boolean flag = bucketExists(bucketName);
-//         if (flag) {
-//             minioClient.putObject(bucketName, objectName, stream, new PutObjectOptions(stream.available(), -1));
-//             ObjectStat statObject = statObject(bucketName, objectName);
-//             if (statObject != null && statObject.length() > 0) {
-//                 return true;
-//             }
-//         }
-//         return false;
-//     }
-//
-//     /**
-//      * 以流的形式获取一个文件对象
-//      *
-//      * @param bucketName 存储桶名称
-//      * @param objectName 存储桶里的对象名称
-//      * @return
-//      */
-//     @SneakyThrows
-//     public InputStream getObject(String bucketName, String objectName) {
-//         boolean flag = bucketExists(bucketName);
-//         if (flag) {
-//             ObjectStat statObject = statObject(bucketName, objectName);
-//             if (statObject != null && statObject.length() > 0) {
-//                 InputStream stream = minioClient.getObject(bucketName, objectName);
-//                 return stream;
-//             }
-//         }
-//         return null;
-//     }
-//
-//     /**
-//      * 以流的形式获取一个文件对象(断点下载)
-//      *
-//      * @param bucketName 存储桶名称
-//      * @param objectName 存储桶里的对象名称
-//      * @param offset     起始字节的位置
-//      * @param length     要读取的长度 (可选,如果无值则代表读到文件结尾)
-//      * @return
-//      */
-//     @SneakyThrows
-//     public InputStream getObject(String bucketName, String objectName, long offset, Long length) {
-//         boolean flag = bucketExists(bucketName);
-//         if (flag) {
-//             ObjectStat statObject = statObject(bucketName, objectName);
-//             if (statObject != null && statObject.length() > 0) {
-//                 InputStream stream = minioClient.getObject(bucketName, objectName, offset, length);
-//                 return stream;
-//             }
-//         }
-//         return null;
-//     }
-//
-//     /**
-//      * 下载并将文件保存到本地
-//      *
-//      * @param bucketName 存储桶名称
-//      * @param objectName 存储桶里的对象名称
-//      * @param fileName   File name
-//      * @return
-//      */
-//     @SneakyThrows
-//     public boolean getObject(String bucketName, String objectName, String fileName) {
-//         boolean flag = bucketExists(bucketName);
-//         if (flag) {
-//             ObjectStat statObject = statObject(bucketName, objectName);
-//             if (statObject != null && statObject.length() > 0) {
-//                 minioClient.getObject(bucketName, objectName, fileName);
-//                 return true;
-//             }
-//         }
-//         return false;
-//     }
-//
-//     /**
-//      * 删除一个对象
-//      *
-//      * @param bucketName 存储桶名称
-//      * @param objectName 存储桶里的对象名称
-//      */
-//     @SneakyThrows
-//     public boolean removeObject(String bucketName, String objectName) {
-//         boolean flag = bucketExists(bucketName);
-//         if (flag) {
-//             minioClient.removeObject(bucketName, objectName);
-//             return true;
-//         }
-//         return false;
-//     }
-//
-//     /**
-//      * 删除指定桶的多个文件对象,返回删除错误的对象列表,全部删除成功,返回空列表
-//      *
-//      * @param bucketName  存储桶名称
-//      * @param objectNames 含有要删除的多个object名称的迭代器对象
-//      * @return
-//      */
-//     @SneakyThrows
-//     public List<String> removeObject(String bucketName, List<String> objectNames) {
-//         List<String> deleteErrorNames = new ArrayList<>();
-//         boolean flag = bucketExists(bucketName);
-//         if (flag) {
-//             Iterable<Result<DeleteError>> results = minioClient.removeObjects(bucketName, objectNames);
-//             for (Result<DeleteError> result : results) {
-//                 DeleteError error = result.get();
-//                 deleteErrorNames.add(error.objectName());
-//             }
-//         }
-//         return deleteErrorNames;
-//     }
-//
-//     /**
-//      * 生成一个给HTTP GET请求用的presigned URL。
-//      * 浏览器/移动端的客户端可以用这个URL进行下载,即使其所在的存储桶是私有的。这个presigned URL可以设置一个失效时间,默认值是7天。
-//      *
-//      * @param bucketName 存储桶名称
-//      * @param objectName 存储桶里的对象名称
-//      * @param expires    失效时间(以秒为单位),默认是7天,不得大于七天
-//      * @return
-//      */
-//     @SneakyThrows
-//     public String presignedGetObject(String bucketName, String objectName, Integer expires) {
-//         boolean flag = bucketExists(bucketName);
-//         String url = "";
-//         if (flag) {
-//             if (expires < 1 || expires > DEFAULT_EXPIRY_TIME) {
-//                 throw new InvalidExpiresRangeException(expires,
-//                         "expires must be in range of 1 to " + DEFAULT_EXPIRY_TIME);
-//             }
-//             url = minioClient.presignedGetObject(bucketName, objectName, expires);
-//         }
-//         return url;
-//     }
-//
-//     /**
-//      * 生成一个给HTTP PUT请求用的presigned URL。
-//      * 浏览器/移动端的客户端可以用这个URL进行上传,即使其所在的存储桶是私有的。这个presigned URL可以设置一个失效时间,默认值是7天。
-//      *
-//      * @param bucketName 存储桶名称
-//      * @param objectName 存储桶里的对象名称
-//      * @param expires    失效时间(以秒为单位),默认是7天,不得大于七天
-//      * @return
-//      */
-//     @SneakyThrows
-//     public String presignedPutObject(String bucketName, String objectName, Integer expires) {
-//         boolean flag = bucketExists(bucketName);
-//         String url = "";
-//         if (flag) {
-//             if (expires < 1 || expires > DEFAULT_EXPIRY_TIME) {
-//                 throw new InvalidExpiresRangeException(expires,
-//                         "expires must be in range of 1 to " + DEFAULT_EXPIRY_TIME);
-//             }
-//             url = minioClient.presignedPutObject(bucketName, objectName, expires);
-//         }
-//         return url;
-//     }
-//
-//     /**
-//      * 获取对象的元数据
-//      *
-//      * @param bucketName 存储桶名称
-//      * @param objectName 存储桶里的对象名称
-//      * @return
-//      */
-//     @SneakyThrows
-//     public ObjectStat statObject(String bucketName, String objectName) {
-//         boolean flag = bucketExists(bucketName);
-//         if (flag) {
-//             ObjectStat statObject = minioClient.statObject(bucketName, objectName);
-//             return statObject;
-//         }
-//         return null;
-//     }
-//
-//     /**
-//      * 文件访问路径
-//      *
-//      * @param bucketName 存储桶名称
-//      * @param objectName 存储桶里的对象名称
-//      * @return
-//      */
-//     @SneakyThrows
-//     public String getObjectUrl(String bucketName, String objectName) {
-//         boolean flag = bucketExists(bucketName);
-//         String url = "";
-//         if (flag) {
-//             url = minioClient.getObjectUrl(bucketName, objectName);
-//         }
-//         return url;
-//     }
-//
-//
-//
-//     public void downloadFile(String bucketName, String fileName, String originalName, HttpServletResponse response) {
-//         try {
-//
-//             InputStream file = minioClient.getObject(bucketName, fileName);
-//             String filename = new String(fileName.getBytes("ISO8859-1"), StandardCharsets.UTF_8);
-//             if (StringUtils.isNotEmpty(originalName)) {
-//                 fileName = originalName;
-//             }
-//             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();
-//         } catch (ErrorResponseException e) {
-//             e.printStackTrace();
-//         } catch (Exception e) {
-//             e.printStackTrace();
-//         }
-//     }
-// }
+package com.pavis.app.saasbacken.utils;
+
+import com.pavis.app.saasbacken.config.MinioConfig;
+import com.pavis.app.saasbacken.exception.OrgException;
+import com.pavis.app.saasbacken.http.ErrorCode;
+import io.minio.*;
+import io.minio.http.Method;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Component;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.annotation.Resource;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+ * @program: push-saas
+ * @description:
+ * @author: Guanzi
+ * @created: 2021/11/02 13:33
+ */
+@Slf4j
+@Component
+public class MinioUtils {
+
+    private static final String NAME_HEAD = "J";
+    private static final String CONTENT_TYPE = "image/jpeg";
+    //MinIO服务的URL
+    private static String minIOUrl;
+    //Access key
+    private static String accessKey;
+    //Secret key
+    private static String secretKey;
+    //存储桶名称
+    private static String bucketName;
+    //文件大小(最大)
+    private static Integer maxFileSize = 10;
+    //签名有效时间  单位秒
+    private static Integer expires;
+
+
+    /**
+     * 桶占位符
+     */
+    private static final String BUCKET_PARAM = "${bucket}";
+    /**
+     * bucket权限-读写
+     */
+    private static final String READ_WRITE = "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:GetBucketLocation\",\"s3:ListBucket\",\"s3:ListBucketMultipartUploads\"],\"Resource\":[\"arn:aws:s3:::" + BUCKET_PARAM + "\"]},{\"Effect\":\"Allow\",\"Principal\":{\"AWS\":[\"*\"]},\"Action\":[\"s3:DeleteObject\",\"s3:GetObject\",\"s3:ListMultipartUploadParts\",\"s3:PutObject\",\"s3:AbortMultipartUpload\"],\"Resource\":[\"arn:aws:s3:::" + BUCKET_PARAM + "/*\"]}]}";
+
+    @Resource
+    private MinioClient minioClient;
+
+    public MinioUtils() {
+    }
+
+
+    public MinioUtils(String bucketName, MinioConfig minioConfig) {
+        this.minIOUrl = minioConfig.getEndpoint();
+        this.accessKey = minioConfig.getAccessKey();
+        this.secretKey = minioConfig.getSecretKey();
+        this.bucketName = bucketName;
+        this.maxFileSize = minioConfig.getMaxFileSize();
+        this.expires = minioConfig.getExpires();
+    }
+
+    /**
+     * 获取文件签名url
+     *
+     * @param fileName 文件名称
+     * @return 文件签名地址
+     */
+    public static String getSignedUrl(String fileName) throws Exception {
+        if (StringUtils.isBlank(fileName)) {
+            throw new OrgException(ErrorCode.FILENAME_NULL.getCode(),ErrorCode.FILENAME_NULL.getMessage());
+        }
+        MinioClient client = MinioClient.builder()
+                .endpoint(minIOUrl)
+                .credentials(accessKey, secretKey)
+                .build();
+        return client.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder()
+                .method(Method.GET)
+                .bucket(bucketName)
+                .object(getFileName(fileName))
+                .expiry(expires).build());
+    }
+
+    /**
+     * 根据图片路径
+     *
+     * @param response
+     * @param imgUrl   网络(服务器)图片路径
+     */
+    public static void getFileIO(HttpServletResponse response, String imgUrl) throws IOException {
+        OutputStream out = null;
+        InputStream inputStream = null;
+        try {
+            HttpURLConnection connection = (HttpURLConnection) new URL(imgUrl).openConnection();
+            connection.setReadTimeout(5000);
+            connection.setConnectTimeout(5000);
+            connection.setRequestMethod("GET");
+            if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
+                inputStream = connection.getInputStream();
+                response.setContentType("image/jpeg");
+                out = response.getOutputStream();
+                //读取文件流
+                int len = 0;
+                byte[] buffer = new byte[1024 * 10];
+                while ((len = inputStream.read(buffer)) != -1) {
+                    out.write(buffer, 0, len);
+                }
+                out.flush();
+            }
+        } catch (IOException e) {
+            System.out.println("获取图片出现异常,图片路径为:" + imgUrl);
+            e.printStackTrace();
+        } finally {
+            if (null != out) {
+                out.close();
+            }
+            if (null != inputStream) {
+                inputStream.close();
+            }
+        }
+
+    }
+
+    /**
+     * 返回文件URL
+     *
+     * @return
+     */
+    public static String setFile(MultipartFile multipartFile) throws Exception {
+        return uploadFiles(setFileName(null, multipartFile), fileVerify(multipartFile));
+    }
+
+
+    /**
+     * 返回文件名称
+     *
+     * @return
+     */
+    public static String upFile(MultipartFile multipartFile) throws Exception {
+        String fileName = setFileName(null, multipartFile);
+        uploadFiles(fileName, fileVerify(multipartFile));
+        return fileName;
+    }
+
+
+    /**
+     * 返回文件URL
+     *
+     * @param fileName    图片名称
+     * @param inputStream
+     * @return
+     */
+    public static String setFile(String fileName, InputStream inputStream) throws Exception {
+        if (StringUtils.isBlank(fileName)) {
+            throw new OrgException(ErrorCode.FILENAME_NULL.getCode(),ErrorCode.FILENAME_NULL.getMessage());
+        }
+        return uploadFiles(fileName, inputStream);
+    }
+
+    /**
+     * 返回文件URL
+     *
+     * @param fileName      图片名称
+     * @param multipartFile 文件
+     * @return 文件路径字符串(不可直接访问)
+     * @throws IOException
+     */
+    public static String setFile(String fileName, MultipartFile multipartFile) throws Exception {
+        return uploadFiles(setFileName(fileName, multipartFile), fileVerify(multipartFile));
+    }
+
+
+    /**
+     * 文件校验
+     */
+    private static InputStream fileVerify(MultipartFile multipartFile) throws IOException {
+        if (null == multipartFile) {
+            throw new OrgException(4035,"请选择文件");
+        }
+        // 文件不大于10M
+        if (!checkFileSize(multipartFile.getSize(), maxFileSize, "M")) {
+            // throw new CustomException("文件大小超限制");
+            throw new OrgException(4036,"文件大小超限制");
+        }
+        return multipartFile.getInputStream();
+    }
+
+
+    /**
+     * 上传文件 (流的形式)
+     *
+     * @return
+     */
+    private static String uploadFiles(String fileName, InputStream inputStream) throws Exception {
+        MinioClient client = MinioClient.builder().endpoint(minIOUrl).credentials(accessKey, secretKey).build();
+        makeBucket(client, bucketName);
+        //设置桶的读写权限
+        client.setBucketPolicy(SetBucketPolicyArgs.builder().bucket(bucketName).config(READ_WRITE.replace(BUCKET_PARAM, bucketName)).build());
+        client.putObject(PutObjectArgs.builder().bucket(bucketName).object(fileName).stream(inputStream, inputStream.available(), -1)
+                .contentType(CONTENT_TYPE).build());
+        return getObjectPrefixUrl(bucketName) + fileName;
+    }
+
+    /**
+     * 校验创建桶
+     *
+     * @param bucketName 桶
+     */
+    private static void makeBucket(MinioClient minioClient, String bucketName) throws Exception {
+        // 判断桶是否存在
+        boolean isExist = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
+        if (!isExist) {
+            log.info("存储桶{}不存在", bucketName);
+            // 新建桶
+            minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
+            log.info("新建存储桶{}", bucketName);
+        }
+    }
+
+
+    /**
+     * 文件url前半段
+     *
+     * @param bucket 桶
+     * @return 前半段
+     */
+    public static String getObjectPrefixUrl(String bucket) {
+        return String.format("%s/%s/", minIOUrl, bucket);
+    }
+
+
+    private static String setFileName(String fileName, MultipartFile multipartFile) {
+        if (StringUtils.isNotBlank(fileName)) {
+            return fileName;
+        }
+        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmss");
+        String[] originalFilename = multipartFile.getOriginalFilename().split("\\.");
+        return NAME_HEAD + simpleDateFormat.format(new Date()) + getRandom() + "." + originalFilename[originalFilename.length - 1];
+    }
+
+    private static int getRandom() {
+        double ran = Math.random() * 9000 + 1000;
+        return (int) ran;
+    }
+
+
+    /**
+     * 判断文件大小
+     *
+     * @param len  文件长度
+     * @param size 限制大小
+     * @param unit 限制单位(B,K,M,G)
+     * @return
+     */
+    public static boolean checkFileSize(Long len, int size, String unit) {
+//        long len = file.length();
+        double fileSize = 0;
+        if ("B".equals(unit.toUpperCase())) {
+            fileSize = (double) len;
+        } else if ("K".equals(unit.toUpperCase())) {
+            fileSize = (double) len / 1024;
+        } else if ("M".equals(unit.toUpperCase())) {
+            fileSize = (double) len / 1048576;
+        } else if ("G".equals(unit.toUpperCase())) {
+            fileSize = (double) len / 1073741824;
+        }
+        if (fileSize > size) {
+            return false;
+        }
+        return true;
+    }
+
+
+    /**
+     * 处理文件名称(当fileName 不是文件名称为文件存储路径地址时)
+     *
+     * @return
+     */
+    private static String getFileName(String fileName) {
+        if (fileName.contains("/")) {
+            String[] split = fileName.split("/");
+            return split[split.length - 1];
+        } else {
+            return fileName;
+        }
+    }
+}

+ 6 - 0
saas-backen/src/main/resources/application-dev.yml

@@ -7,14 +7,20 @@ spring:
     password: root
   # minio配置
   minio:
+    # Minio服务器地址
     endpoint: http://192.168.1.139:9000
     port: 9001
     create-bucket: true
     bucketName: push-test
+    # Minio服务器账号
     accessKey: guanz
+    # Minio服务器密码
     secretKey: guanz@123
     secure: false
     configDir: /home/push
+    # 文件大小 单位M
+    maxFileSize: 10
+    expires: 604800
 # es配置
 elasticsearch:
   hostname: 127.0.0.1

+ 2 - 1
saas-backen/src/main/resources/error.properties

@@ -14,5 +14,6 @@ get_user_info_failed=\u767B\u5F55\u5931\u8D25\uFF0C\u7528\u6237\u4FE1\u606F\u83B
 login_failure=\u767B\u5F55\u5931\u6548\uFF0C\u8BF7\u91CD\u65B0\u767B\u5F55\u3002
 request_org_failed=\u7EC4\u7EC7\u5217\u8868\u83B7\u53D6\u5931\u8D25\u3002
 is_relation_exist=\u6743\u9650\u5DF2\u5B58\u5728\uFF0C\u8BF7\u52FF\u91CD\u590D\u6DFB\u52A0\u3002
-qa_no_response=\u95EE\u7B54\u65E0\u54CD\u5E94,\u7B97\u6CD5\u51FA\u9519\uFF01
+qa_no_response=\u95EE\u7B54\u65E0\u54CD\u5E94,\u7B97\u6CD5\u51FA\u9519!
 illegal_argument=\u53C2\u6570\u4E0D\u5408\u6CD5!
+filename_null=\u6587\u4EF6\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A!