From be812198b1c18cf5b79f2cdc69d2f7c3c70eff51 Mon Sep 17 00:00:00 2001
From: liusheng <337615773@qq.com>
Date: 星期二, 20 六月 2023 14:23:43 +0800
Subject: [PATCH] “文件管理“ 代码提交

---
 smartor/src/main/java/com/smartor/domain/PatArchiveReq.java                               |    2 
 smartor/src/main/java/com/smartor/domain/MinioFile.java                                   |   77 +++
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/smartor/BaseTagcategoryController.java |    9 
 smartor/src/main/resources/mapper/smartor/MinioFileMapper.xml                             |  122 +++++
 ruoyi-common/src/main/java/com/ruoyi/common/utils/MinioClientUtils.java                   |  466 ++++++++++++++++++++
 smartor/src/main/java/com/smartor/domain/MinioResponseDTO.java                            |   15 
 smartor/src/main/java/com/smartor/service/IMinioFileService.java                          |   96 ++++
 ruoyi-common/src/main/java/com/ruoyi/common/config/MinioConfig.java                       |   27 +
 ruoyi-admin/src/main/resources/application.yml                                            |   53 +
 ruoyi-common/pom.xml                                                                      |    6 
 smartor/src/main/resources/mapper/smartor/PatArchiveMapper.xml                            |    9 
 smartor/src/main/java/com/smartor/mapper/MinioFileMapper.java                             |   63 ++
 smartor/src/main/resources/mapper/smartor/BaseTagcategoryMapper.xml                       |    6 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/smartor/MinioFileController.java       |  150 ++++++
 smartor/src/main/java/com/smartor/domain/TreeNode.java                                    |   31 +
 smartor/src/main/java/com/smartor/service/impl/MinioFileServiceImpl.java                  |  246 ++++++++++
 16 files changed, 1,349 insertions(+), 29 deletions(-)

diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/smartor/BaseTagcategoryController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/smartor/BaseTagcategoryController.java
index ca41db4..452f242 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/smartor/BaseTagcategoryController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/smartor/BaseTagcategoryController.java
@@ -10,6 +10,7 @@
 import com.smartor.service.IBaseTagcategoryService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
+import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.web.bind.annotation.*;
@@ -24,6 +25,7 @@
  * @date 2023-06-15
  */
 @Api(description = "鏍囩鍒嗙被")
+@Slf4j
 @RestController
 @RequestMapping("/system/tagcategory")
 public class BaseTagcategoryController extends BaseController {
@@ -67,6 +69,7 @@
      */
     @PreAuthorize("@ss.hasPermi('system:tagcategory:add')")
     @Log(title = "鏍囩鍒嗙被", businessType = BusinessType.INSERT)
+    @ApiOperation("鏂板鏍囩鍒嗙被")
     @PostMapping
     public AjaxResult add(@RequestBody BaseTagcategory baseTagcategory) {
         return toAjax(baseTagcategoryService.insertBaseTagcategory(baseTagcategory));
@@ -77,16 +80,18 @@
      */
     @PreAuthorize("@ss.hasPermi('system:tagcategory:edit')")
     @Log(title = "鏍囩鍒嗙被", businessType = BusinessType.UPDATE)
+    @ApiOperation("淇敼鏍囩鍒嗙被")
     @PutMapping
     public AjaxResult edit(@RequestBody BaseTagcategory baseTagcategory) {
         return toAjax(baseTagcategoryService.updateBaseTagcategory(baseTagcategory));
     }
 
     /**
-     * 鍒犻櫎鏍囩鍒嗙被
+     * 鏍规嵁鍒嗙被ID鍒犻櫎鏍囩鍒嗙被
      */
     @PreAuthorize("@ss.hasPermi('system:tagcategory:remove')")
     @Log(title = "鏍囩鍒嗙被", businessType = BusinessType.DELETE)
+    @ApiOperation("鏍规嵁鍒嗙被ID鍒犻櫎鏍囩鍒嗙被")
     @DeleteMapping("/{tagcategoryids}")
     public AjaxResult remove(@PathVariable Long[] tagcategoryids) {
         return toAjax(baseTagcategoryService.deleteBaseTagcategoryByTagcategoryids(tagcategoryids));
@@ -100,4 +105,6 @@
     public TableDataInfo baseTagCategoryByName(@RequestParam("name") String name) {
         return getDataTable(baseTagcategoryService.baseTagCategoryByName(name));
     }
+
+
 }
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/smartor/MinioFileController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/smartor/MinioFileController.java
new file mode 100644
index 0000000..87f8f92
--- /dev/null
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/smartor/MinioFileController.java
@@ -0,0 +1,150 @@
+package com.ruoyi.web.controller.smartor;
+
+import com.ruoyi.common.annotation.Log;
+import com.ruoyi.common.core.controller.BaseController;
+import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.page.TableDataInfo;
+import com.ruoyi.common.enums.BusinessType;
+import com.ruoyi.common.utils.poi.ExcelUtil;
+import com.smartor.domain.MinioFile;
+import com.smartor.service.IMinioFileService;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiOperation;
+import org.apache.commons.collections4.CollectionUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletResponse;
+import java.util.List;
+
+/**
+ * 銆愯濉啓鍔熻兘鍚嶇О銆慍ontroller
+ *
+ * @author ruoyi
+ * @date 2023-06-19
+ */
+@Api(description = "鏂囦欢绠$悊锛堟枃妗c�佸浘鐗�...锛�")
+@RestController
+@RequestMapping("/system/file")
+public class MinioFileController extends BaseController {
+    @Autowired
+    private IMinioFileService minioFileService;
+
+    /**
+     * 鏌ヨ銆愯濉啓鍔熻兘鍚嶇О銆戝垪琛�
+     */
+    @PreAuthorize("@ss.hasPermi('system:file:list')")
+    @GetMapping("/list")
+    public TableDataInfo list(MinioFile minioFile) {
+        startPage();
+        List<MinioFile> list = minioFileService.selectMinioFileList(minioFile);
+        return getDataTable(list);
+    }
+
+    /**
+     * 瀵煎嚭銆愯濉啓鍔熻兘鍚嶇О銆戝垪琛�
+     */
+    @PreAuthorize("@ss.hasPermi('system:file:export')")
+    @Log(title = "銆愯濉啓鍔熻兘鍚嶇О銆�", businessType = BusinessType.EXPORT)
+    @PostMapping("/export")
+    public void export(HttpServletResponse response, MinioFile minioFile) {
+        List<MinioFile> list = minioFileService.selectMinioFileList(minioFile);
+        ExcelUtil<MinioFile> util = new ExcelUtil<MinioFile>(MinioFile.class);
+        util.exportExcel(response, list, "銆愯濉啓鍔熻兘鍚嶇О銆戞暟鎹�");
+    }
+
+    /**
+     * 鑾峰彇銆愯濉啓鍔熻兘鍚嶇О銆戣缁嗕俊鎭�
+     */
+    @PreAuthorize("@ss.hasPermi('system:file:query')")
+    @GetMapping(value = "/{id}")
+    public AjaxResult getInfo(@PathVariable("id") Long id) {
+        return success(minioFileService.selectMinioFileById(id));
+    }
+
+    /**
+     * 鏂板銆愯濉啓鍔熻兘鍚嶇О銆�
+     */
+    @PreAuthorize("@ss.hasPermi('system:file:add')")
+    @Log(title = "銆愯濉啓鍔熻兘鍚嶇О銆�", businessType = BusinessType.INSERT)
+    @PostMapping
+    public AjaxResult add(@RequestBody MinioFile minioFile) {
+        return toAjax(minioFileService.insertMinioFile(minioFile));
+    }
+
+    /**
+     * 淇敼銆愯濉啓鍔熻兘鍚嶇О銆�
+     */
+    @PreAuthorize("@ss.hasPermi('system:file:edit')")
+    @Log(title = "銆愯濉啓鍔熻兘鍚嶇О銆�", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult edit(@RequestBody MinioFile minioFile) {
+        return toAjax(minioFileService.updateMinioFile(minioFile));
+    }
+
+    /**
+     * 鍒犻櫎銆愯濉啓鍔熻兘鍚嶇О銆�
+     */
+    @PreAuthorize("@ss.hasPermi('system:file:remove')")
+    @Log(title = "銆愯濉啓鍔熻兘鍚嶇О銆�", businessType = BusinessType.DELETE)
+    @DeleteMapping("/{ids}")
+    public AjaxResult remove(@PathVariable Long[] ids) {
+        return toAjax(minioFileService.deleteMinioFileByIds(ids));
+    }
+
+
+    /**
+     * 涓婁紶鏂囦欢鍒版枃浠剁鐞�,鏀寔鎵归噺涓婁紶
+     *
+     * @param files
+     * @return
+     */
+    @PostMapping(value = {"/admin/uploadFile"})
+    @ResponseBody
+    @ApiOperation(value = "涓婁紶鏂囦欢鍒版枃浠剁鐞�,鏀寔鎵归噺涓婁紶")
+    @ApiImplicitParam(name = "files", value = "鏂囦欢瀵硅薄", dataType = "File")
+    public AjaxResult commonUploadFile(@RequestParam("path") String path, @RequestParam("files") List<MultipartFile> files) {
+        if (CollectionUtils.isEmpty(files)) {
+            return error("鏈�夋嫨鏂囦欢锛�");
+        }
+        return success(minioFileService.commonUploadFile(path, files));
+    }
+
+    /**
+     * 鑾峰彇锛堝鏁欙級寮曠敤妯℃澘
+     */
+    @PreAuthorize("@ss.hasPermi('system:file:list')")
+    @ApiOperation(value = "鑾峰彇锛堝鏁欙級寮曠敤妯℃澘")
+    @GetMapping("/getEduTemplage")
+    public AjaxResult getEduTemplage() {
+        //  startPage();
+        return success(minioFileService.getEduTemplage());
+    }
+
+    /**
+     * 涓嬭浇鏂囦欢锛屼互娴佺殑褰㈠紡杩斿洖
+     *
+     * @return
+     */
+    @ApiOperation(value = "涓嬭浇鏂囦欢锛屼互杈撳嚭娴佺殑褰㈠紡杩斿洖, 鍏ュ弬鐨刦ileName涓哄叏璺緞鏂囦欢鍚�")
+    @GetMapping("/downloadFile")
+    public void downloadFile(HttpServletResponse response, @RequestParam("fileName") String fileName) {
+        minioFileService.downloadFile(response, fileName);
+    }
+
+
+    /**
+     * 鑾峰彇鍥剧墖銆侀煶棰戙�佽棰� 鐨刄RL
+     *
+     * @return
+     */
+    @ApiOperation(value = "鑾峰彇鍥剧墖銆侀煶棰戙�佽棰� 鐨刄RL, 鍏ュ弬鐨刦ileName涓哄叏璺緞鏂囦欢鍚�,expires涓洪摼鎺ヨ繃鏈熸椂闂�")
+    @GetMapping("/getFileUrl")
+    public AjaxResult getFileUrl(@RequestParam("fileName") String fileName, @RequestParam("expires") Integer expires) {
+        return success(minioFileService.getFileUrl(fileName, expires));
+    }
+
+}
diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml
index f54c5cb..de72b37 100644
--- a/ruoyi-admin/src/main/resources/application.yml
+++ b/ruoyi-admin/src/main/resources/application.yml
@@ -53,15 +53,15 @@
   messages:
     # 鍥介檯鍖栬祫婧愭枃浠惰矾寰�
     basename: i18n/messages
-  profiles: 
+  profiles:
     active: druid
   # 鏂囦欢涓婁紶
   servlet:
-     multipart:
-       # 鍗曚釜鏂囦欢澶у皬
-       max-file-size:  10MB
-       # 璁剧疆鎬讳笂浼犵殑鏂囦欢澶у皬
-       max-request-size:  20MB
+    multipart:
+      # 鍗曚釜鏂囦欢澶у皬
+      max-file-size: 500MB
+      # 璁剧疆鎬讳笂浼犵殑鏂囦欢澶у皬
+      max-request-size: 750MB
   # 鏈嶅姟妯″潡
   devtools:
     restart:
@@ -90,29 +90,38 @@
         # #杩炴帴姹犳渶澶ч樆濉炵瓑寰呮椂闂达紙浣跨敤璐熷�艰〃绀烘病鏈夐檺鍒讹級
         max-wait: -1ms
 
+# minio鏂囦欢绠$悊杩炴帴
+minio:
+  endpoint: http://192.168.1.4
+  port: 9002
+  accessKey: lihu
+  secretKey: lihu@123
+  bucketName: lihu
+  secure: false
+
 # token閰嶇疆
 token:
-    # 浠ょ墝鑷畾涔夋爣璇�
-    header: Authorization
-    # 浠ょ墝瀵嗛挜
-    secret: abcdefghijklmnopqrstuvwxyz
-    # 浠ょ墝鏈夋晥鏈燂紙榛樿30鍒嗛挓锛�
-    expireTime: 30
-  
+  # 浠ょ墝鑷畾涔夋爣璇�
+  header: Authorization
+  # 浠ょ墝瀵嗛挜
+  secret: abcdefghijklmnopqrstuvwxyz
+  # 浠ょ墝鏈夋晥鏈燂紙榛樿30鍒嗛挓锛�
+  expireTime: 30
+
 # MyBatis閰嶇疆
 mybatis:
-    # 鎼滅储鎸囧畾鍖呭埆鍚�
-    typeAliasesPackage: com.ruoyi.**.domain,com.smartor.domain
-    # 閰嶇疆mapper鐨勬壂鎻忥紝鎵惧埌鎵�鏈夌殑mapper.xml鏄犲皠鏂囦欢
-    mapperLocations: classpath*:mapper/**/*Mapper.xml
-    # 鍔犺浇鍏ㄥ眬鐨勯厤缃枃浠�
-    configLocation: classpath:mybatis/mybatis-config.xml
+  # 鎼滅储鎸囧畾鍖呭埆鍚�
+  typeAliasesPackage: com.ruoyi.**.domain,com.smartor.domain
+  # 閰嶇疆mapper鐨勬壂鎻忥紝鎵惧埌鎵�鏈夌殑mapper.xml鏄犲皠鏂囦欢
+  mapperLocations: classpath*:mapper/**/*Mapper.xml
+  # 鍔犺浇鍏ㄥ眬鐨勯厤缃枃浠�
+  configLocation: classpath:mybatis/mybatis-config.xml
 
 # PageHelper鍒嗛〉鎻掍欢
-pagehelper: 
+pagehelper:
   helperDialect: mysql
   supportMethodsArguments: true
-  params: count=countSql 
+  params: count=countSql
 
 # Swagger閰嶇疆
 swagger:
@@ -122,7 +131,7 @@
   pathMapping: /dev-api
 
 # 闃叉XSS鏀诲嚮
-xss: 
+xss:
   # 杩囨护寮�鍏�
   enabled: true
   # 鎺掗櫎閾炬帴锛堝涓敤閫楀彿鍒嗛殧锛�
diff --git a/ruoyi-common/pom.xml b/ruoyi-common/pom.xml
index 0ee06f4..d5d43dd 100644
--- a/ruoyi-common/pom.xml
+++ b/ruoyi-common/pom.xml
@@ -17,6 +17,12 @@
 
     <dependencies>
 
+        <dependency>
+            <groupId>io.minio</groupId>
+            <artifactId>minio</artifactId>
+            <version>7.1.0</version>
+        </dependency>
+
         <!-- Spring妗嗘灦鍩烘湰鐨勬牳蹇冨伐鍏� -->
         <dependency>
             <groupId>org.springframework</groupId>
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/config/MinioConfig.java b/ruoyi-common/src/main/java/com/ruoyi/common/config/MinioConfig.java
new file mode 100644
index 0000000..970e5a0
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/config/MinioConfig.java
@@ -0,0 +1,27 @@
+package com.ruoyi.common.config;
+
+import io.minio.MinioClient;
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.stereotype.Component;
+
+@Configuration
+@Component
+@ConfigurationProperties(prefix = "minio")
+@Data
+public class MinioConfig {
+    private String endpoint;
+    private int port;
+    private String accessKey;
+    private String secretKey;
+    private Boolean secure;
+    private String bucketName;
+
+    @Bean
+    public MinioClient getMinioClient() {
+        MinioClient minioClient = MinioClient.builder().endpoint(endpoint, port, secure).credentials(accessKey, secretKey).build();
+        return minioClient;
+    }
+}
diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/utils/MinioClientUtils.java b/ruoyi-common/src/main/java/com/ruoyi/common/utils/MinioClientUtils.java
new file mode 100644
index 0000000..a17e253
--- /dev/null
+++ b/ruoyi-common/src/main/java/com/ruoyi/common/utils/MinioClientUtils.java
@@ -0,0 +1,466 @@
+package com.ruoyi.common.utils;
+
+
+import io.minio.*;
+import io.minio.errors.*;
+import io.minio.http.Method;
+import io.minio.messages.Bucket;
+import io.minio.messages.DeleteError;
+import io.minio.messages.DeleteObject;
+import io.minio.messages.Item;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.annotation.Resource;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.security.InvalidKeyException;
+import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
+import java.util.List;
+
+@Component
+@Slf4j
+public class MinioClientUtils {
+    @Resource
+    private MinioClient minioClient;
+
+    private static final int DEFAULT_EXPIRY_TIME = 999999 * 24 * 3600;
+
+    /**
+     * 妫�鏌ュ瓨鍌ㄦ《鏄惁瀛樺湪
+     *
+     * @param bucketName 瀛樺偍妗跺悕绉�
+     * @return boolean
+     */
+    public boolean bucketExists(String bucketName) throws Exception {
+        boolean flag = false;
+        flag = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
+        if (flag) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * 鍒涘缓瀛樺偍妗�
+     *
+     * @param bucketName 瀛樺偍妗跺悕绉�
+     */
+    public boolean makeBucket(String bucketName) throws Exception {
+        boolean flag = bucketExists(bucketName);
+        if (!flag) {
+            minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * 鍒楀嚭鎵�鏈夊瓨鍌ㄦ《鍚嶇О
+     *
+     * @return List<String>
+     */
+    public List<String> listBucketNames() throws Exception {
+        List<Bucket> bucketList = listBuckets();
+        List<String> bucketListName = new ArrayList<>();
+        for (Bucket bucket : bucketList) {
+            bucketListName.add(bucket.name());
+        }
+        return bucketListName;
+    }
+
+    /**
+     * 鍒楀嚭鎵�鏈夊瓨鍌ㄦ《
+     *
+     * @return List<Bucket>
+     */
+    public List<Bucket> listBuckets() throws Exception {
+        return minioClient.listBuckets();
+    }
+
+    /**
+     * 鍒犻櫎瀛樺偍妗�
+     *
+     * @param bucketName 瀛樺偍妗跺悕绉�
+     * @return boolean
+     */
+    public boolean removeBucket(String bucketName) throws Exception {
+        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(RemoveBucketArgs.builder().bucket(bucketName).build());
+            flag = bucketExists(bucketName);
+            if (!flag) {
+                return true;
+            }
+
+        }
+        return false;
+    }
+
+    /**
+     * 鍒楀嚭瀛樺偍妗朵腑鐨勬墍鏈夊璞″悕绉�
+     *
+     * @param bucketName 瀛樺偍妗跺悕绉�
+     * @return List<String>
+     */
+    public List<String> listObjectNames(String bucketName) throws Exception {
+        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 Iterable<Result < Item>>
+     */
+    public Iterable<Result<Item>> listObjects(String bucketName) throws Exception {
+        boolean flag = bucketExists(bucketName);
+        if (flag) {
+            return minioClient.listObjects(ListObjectsArgs.builder().bucket(bucketName).build());
+        }
+        return null;
+    }
+
+    /**
+     * 閫氳繃鏂囦欢涓婁紶鍒板璞�
+     *
+     * @param bucketName 瀛樺偍妗跺悕绉�
+     * @param objectName 瀛樺偍妗堕噷鐨勫璞″悕绉�
+     * @param fileName   File name
+     * @return boolean
+     */
+    public boolean uploadObject(String bucketName, String objectName, String fileName) throws Exception {
+        boolean flag = bucketExists(bucketName);
+        if (flag) {
+            minioClient.uploadObject(UploadObjectArgs.builder().bucket(bucketName).object(objectName).filename(fileName).build());
+            ObjectStat statObject = statObject(bucketName, objectName);
+            if (statObject != null && statObject.length() > 0) {
+                return true;
+            }
+        }
+        return false;
+
+    }
+
+    /**
+     * 鏂囦欢涓婁紶
+     *
+     * @param bucketName    瀛樺偍鎹呭悕绉�
+     * @param multipartFile 鏂囦欢
+     * @param filename      鏂囦欢鍚�
+     */
+    public void putObject(String bucketName, MultipartFile multipartFile, String filename) throws Exception {
+        PutObjectOptions putObjectOptions = new PutObjectOptions(multipartFile.getSize(), PutObjectOptions.MIN_MULTIPART_SIZE);
+        putObjectOptions.setContentType(multipartFile.getContentType());
+        minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(filename).stream(multipartFile.getInputStream(), multipartFile.getSize(), -1).contentType(multipartFile.getContentType()).build());
+    }
+
+    /**
+     * 閫氳繃InputStream涓婁紶瀵硅薄
+     *
+     * @param bucketName  瀛樺偍妗跺悕绉�
+     * @param objectName  瀛樺偍妗堕噷鐨勫璞″悕绉�
+     * @param inputStream 瑕佷笂浼犵殑娴�
+     * @param contentType 涓婁紶鐨勬枃浠剁被鍨� 渚嬪 video/mp4  image/jpg
+     * @return boolean
+     */
+    public boolean putObject(String bucketName, String objectName, InputStream inputStream, String contentType) throws Exception {
+        boolean flag = bucketExists(bucketName);
+        if (flag) {
+            minioClient.putObject(PutObjectArgs.builder().bucket(bucketName).object(objectName).stream(
+                    //涓嶆竻妤氭枃浠剁殑澶у皬鏃讹紝鍙互浼�-1锛�10485760銆傚鏋滅煡閬撳ぇ灏忎篃鍙互浼犲叆size锛宲artsize銆�
+                    inputStream, -1, 10485760).contentType(contentType).build());
+            ObjectStat statObject = statObject(bucketName, objectName);
+            if (statObject != null && statObject.length() > 0) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 浠ユ祦鐨勫舰寮忚幏鍙栦竴涓枃浠跺璞�
+     *
+     * @param bucketName 瀛樺偍妗跺悕绉�
+     * @param objectName 瀛樺偍妗堕噷鐨勫璞″悕绉�
+     * @return InputStream
+     */
+    public InputStream getObject(String bucketName, String objectName) throws Exception {
+        boolean flag = bucketExists(bucketName);
+        if (flag) {
+            ObjectStat statObject = statObject(bucketName, objectName);
+            if (statObject != null && statObject.length() > 0) {
+                InputStream stream = minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(objectName).build());
+                return stream;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * 浠ユ祦鐨勫舰寮忚幏鍙栦竴涓枃浠跺璞★紙鏂偣涓嬭浇锛�
+     *
+     * @param bucketName 瀛樺偍妗跺悕绉�
+     * @param objectName 瀛樺偍妗堕噷鐨勫璞″悕绉�
+     * @param offset     璧峰瀛楄妭鐨勪綅缃�
+     * @param length     瑕佽鍙栫殑闀垮害 (鍙�夛紝濡傛灉鏃犲�煎垯浠h〃璇诲埌鏂囦欢缁撳熬)
+     * @return InputStream
+     */
+    public InputStream getObject(String bucketName, String objectName, long offset, Long length) throws Exception {
+        boolean flag = bucketExists(bucketName);
+        if (flag) {
+            ObjectStat statObject = statObject(bucketName, objectName);
+            if (statObject != null && statObject.length() > 0) {
+                InputStream stream = minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(objectName).offset(1024L).length(4096L).build());
+                return stream;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * 涓嬭浇骞跺皢鏂囦欢淇濆瓨鍒版湰鍦�
+     *
+     * @param bucketName 瀛樺偍妗跺悕绉�
+     * @param objectName 瀛樺偍妗堕噷鐨勫璞″悕绉�
+     * @param fileName   File name
+     * @return boolean
+     */
+    public boolean downloadObject(String bucketName, String objectName, String fileName) throws Exception {
+        boolean flag = bucketExists(bucketName);
+        if (flag) {
+            ObjectStat statObject = statObject(bucketName, objectName);
+            if (statObject != null && statObject.length() > 0) {
+                minioClient.downloadObject(DownloadObjectArgs.builder().bucket(bucketName).object(objectName).filename(fileName).build());
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * 鍒犻櫎涓�涓璞�
+     *
+     * @param bucketName 瀛樺偍妗跺悕绉�
+     * @param objectName 瀛樺偍妗堕噷鐨勫璞″悕绉�
+     */
+    public boolean removeObject(String bucketName, String objectName) throws Exception {
+        boolean flag = bucketExists(bucketName);
+        if (flag) {
+            minioClient.removeObject(RemoveObjectArgs.builder().bucket(bucketName).object(objectName).build());
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * 鍒犻櫎鎸囧畾妗剁殑澶氫釜鏂囦欢瀵硅薄,杩斿洖鍒犻櫎閿欒鐨勫璞″垪琛紝鍏ㄩ儴鍒犻櫎鎴愬姛锛岃繑鍥炵┖鍒楄〃
+     *
+     * @param bucketName  瀛樺偍妗跺悕绉�
+     * @param objectNames 鍚湁瑕佸垹闄ょ殑澶氫釜object鍚嶇О鐨勮凯浠e櫒瀵硅薄
+     * @return eg:
+     * List<DeleteObject> objects = new LinkedList<>();
+     * objects.add(new DeleteObject("my-objectname1"));
+     * objects.add(new DeleteObject("my-objectname2"));
+     * objects.add(new DeleteObject("my-objectname3"));
+     */
+    public List<String> removeObjects(String bucketName, List<DeleteObject> objectNames) throws Exception {
+        List<String> deleteErrorNames = new ArrayList<>();
+        boolean flag = bucketExists(bucketName);
+        if (flag) {
+            Iterable<Result<DeleteError>> results = minioClient.removeObjects(RemoveObjectsArgs.builder().bucket(bucketName).objects(objectNames).build());
+            for (Result<DeleteError> result : results) {
+                DeleteError error = result.get();
+                deleteErrorNames.add(error.objectName());
+            }
+        }
+        return deleteErrorNames;
+    }
+
+    /**
+     * 鐢熸垚涓�涓粰HTTP GET璇锋眰鐢ㄧ殑presigned URL銆�
+     * 娴忚鍣�/绉诲姩绔殑瀹㈡埛绔彲浠ョ敤杩欎釜URL杩涜
+     * 锛屽嵆浣垮叾鎵�鍦ㄧ殑瀛樺偍妗舵槸绉佹湁鐨勩�傝繖涓猵resigned URL鍙互璁剧疆涓�涓け鏁堟椂闂达紝榛樿鍊兼槸999999澶┿��
+     *
+     * @param bucketName 瀛樺偍妗跺悕绉�
+     * @param objectName 瀛樺偍妗堕噷鐨勫璞″悕绉�
+     * @param expires    澶辨晥鏃堕棿锛堜互绉掍负鍗曚綅锛夛紝榛樿鏄�999999澶╋紝涓嶅緱澶т簬999999澶�
+     * @return
+     */
+    public String getPresignedObjectUrl(String bucketName, String objectName, Integer expires) throws Exception {
+        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);
+            }
+            try {
+                url = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().method(Method.GET).bucket(bucketName).object(objectName).expiry(expires)//鍔ㄦ�佸弬鏁�
+                        //                       .expiry(24 * 60 * 60)//鐢ㄧ鏉ヨ绠椾竴澶╂椂闂存湁鏁堟湡
+//                        .expiry(1, TimeUnit.DAYS)//鎸夊ぉ浼犲弬
+//                        .expiry(1, TimeUnit.HOURS)//鎸夊皬鏃朵紶鍙傛暟
+                        .build());
+            } catch (ErrorResponseException | InsufficientDataException | InternalException | InvalidBucketNameException | InvalidExpiresRangeException | InvalidKeyException | InvalidResponseException | IOException | NoSuchAlgorithmException | ServerException | XmlParserException e) {
+                e.printStackTrace();
+            }
+        }
+        return url;
+    }
+
+    /**
+     * 鐢熸垚涓�涓粰HTTP PUT璇锋眰鐢ㄧ殑presigned URL銆�
+     * 娴忚鍣�/绉诲姩绔殑瀹㈡埛绔彲浠ョ敤杩欎釜URL杩涜涓婁紶锛屽嵆浣垮叾鎵�鍦ㄧ殑瀛樺偍妗舵槸绉佹湁鐨勩�傝繖涓猵resigned URL鍙互璁剧疆涓�涓け鏁堟椂闂达紝榛樿鍊兼槸7澶┿��
+     *
+     * @param bucketName 瀛樺偍妗跺悕绉�
+     * @param objectName 瀛樺偍妗堕噷鐨勫璞″悕绉�
+     * @param expires    澶辨晥鏃堕棿锛堜互绉掍负鍗曚綅锛夛紝榛樿鏄�7澶╋紝涓嶅緱澶т簬涓冨ぉ
+     * @return String
+     */
+    public String presignedPutObject(String bucketName, String objectName, Integer expires) throws Exception {
+        boolean flag = bucketExists(bucketName);
+        String url = "";
+        if (flag) {
+            if (expires < 1 || expires > DEFAULT_EXPIRY_TIME) {
+                try {
+                    throw new InvalidExpiresRangeException(expires, "expires must be in range of 1 to " + DEFAULT_EXPIRY_TIME);
+                } catch (InvalidExpiresRangeException e) {
+                    e.printStackTrace();
+                }
+            }
+            try {
+                url = minioClient.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder().method(Method.PUT).bucket(bucketName).object(objectName).expiry(expires)//鍔ㄦ�佸弬鏁�
+                        //                       .expiry(24 * 60 * 60)//鐢ㄧ鏉ヨ绠椾竴澶╂椂闂存湁鏁堟湡
+//                        .expiry(1, TimeUnit.DAYS)//鎸夊ぉ浼犲弬
+//                        .expiry(1, TimeUnit.HOURS)//鎸夊皬鏃朵紶鍙傛暟
+                        .build());
+            } catch (ErrorResponseException | InsufficientDataException e) {
+                e.printStackTrace();
+            } catch (InternalException e) {
+                log.error("InternalException", e);
+            } catch (InvalidBucketNameException e) {
+                log.error("InvalidBucketNameException", e);
+            } catch (InvalidExpiresRangeException e) {
+                log.error("InvalidExpiresRangeException", e);
+            } catch (InvalidKeyException e) {
+                log.error("InvalidKeyException", e);
+            } catch (InvalidResponseException e) {
+                log.error("InvalidResponseException", e);
+            } catch (IOException e) {
+                log.error("IOException", e);
+            } catch (NoSuchAlgorithmException e) {
+                log.error("NoSuchAlgorithmException", e);
+            } catch (ServerException e) {
+                log.error("ServerException", e);
+            } catch (XmlParserException e) {
+                log.error("XmlParserException", e);
+            }
+        }
+        return url;
+    }
+
+    /**
+     * 鑾峰彇瀵硅薄鐨勫厓鏁版嵁
+     *
+     * @param bucketName 瀛樺偍妗跺悕绉�
+     * @param objectName 瀛樺偍妗堕噷鐨勫璞″悕绉�
+     * @return
+     */
+    public ObjectStat statObject(String bucketName, String objectName) throws Exception {
+        boolean flag = bucketExists(bucketName);
+        if (flag) {
+            ObjectStat statObject = null;
+
+            statObject = minioClient.statObject(StatObjectArgs.builder().bucket(bucketName).object(objectName).build());
+
+            return statObject;
+        }
+        return null;
+    }
+
+    /**
+     * 鏂囦欢璁块棶璺緞
+     *
+     * @param bucketName 瀛樺偍妗跺悕绉�
+     * @param objectName 瀛樺偍妗堕噷鐨勫璞″悕绉�
+     * @return String
+     */
+    public String getObjectUrl(String bucketName, String objectName) throws Exception {
+        boolean flag = bucketExists(bucketName);
+        String url = "";
+        if (flag) {
+            try {
+                url = minioClient.getObjectUrl(bucketName, objectName);
+            } catch (ErrorResponseException e) {
+                log.error("XmlParserException", e);
+            } catch (InsufficientDataException e) {
+                log.error("InsufficientDataException", e);
+            } catch (InternalException e) {
+                log.error("InternalException", e);
+            } catch (InvalidKeyException e) {
+                log.error("InvalidKeyException", e);
+            } catch (InvalidResponseException e) {
+                log.error("InvalidResponseException", e);
+            } catch (IOException e) {
+                log.error("IOException", e);
+            } catch (NoSuchAlgorithmException e) {
+                log.error("NoSuchAlgorithmException", e);
+            } catch (ServerException e) {
+                log.error("ServerException", e);
+            } catch (XmlParserException e) {
+                log.error("XmlParserException", e);
+            }
+        }
+        return url;
+    }
+
+
+    public void downloadFile(String bucketName, String fileName, String originalName, HttpServletResponse response) {
+        try {
+
+            InputStream file = minioClient.getObject(GetObjectArgs.builder().bucket(bucketName).object(fileName).build());
+            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) {
+            log.error("ErrorResponseException", e);
+        } catch (Exception e) {
+            log.error("Exception", e);
+        }
+    }
+
+}
diff --git a/smartor/src/main/java/com/smartor/domain/MinioFile.java b/smartor/src/main/java/com/smartor/domain/MinioFile.java
new file mode 100644
index 0000000..ea43e13
--- /dev/null
+++ b/smartor/src/main/java/com/smartor/domain/MinioFile.java
@@ -0,0 +1,77 @@
+package com.smartor.domain;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+import com.ruoyi.common.annotation.Excel;
+import com.ruoyi.common.core.domain.BaseEntity;
+
+/**
+ * 銆愯濉啓鍔熻兘鍚嶇О銆戝璞� minio_file
+ *
+ * @author ruoyi
+ * @date 2023-06-19
+ */
+@Data
+@ApiModel(value = "MinioFile", description = "鏍囩鍒嗙被瀵硅薄")
+public class MinioFile extends BaseEntity {
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 鏂囦欢id
+     */
+    @ApiModelProperty(value = "鏂囦欢id")
+    private Long id;
+
+    /**
+     * 鍘熷鏂囦欢鍚嶇О
+     */
+    @Excel(name = "鍘熷鏂囦欢鍚嶇О")
+    @ApiModelProperty(value = "鍘熷鏂囦欢鍚嶇О")
+    private String originalFileName;
+
+    /**
+     * 鏂囦欢鎷撳睍鍚�
+     */
+    @Excel(name = "鏂囦欢鎷撳睍鍚�")
+    @ApiModelProperty(value = "鏂囦欢鎷撳睍鍚�")
+    private String fileExtName;
+
+    /**
+     * 鏂囦欢澶у皬(鍗曚綅锛氬瓧鑺傦級
+     */
+    @Excel(name = "鏂囦欢澶у皬(鍗曚綅锛氬瓧鑺傦級")
+    @ApiModelProperty(value = "鏂囦欢澶у皬(鍗曚綅锛氬瓧鑺傦級")
+    private Long fileSize;
+
+    /**
+     * 瀛樺叆minio鏃剁殑鏂囦欢鍚嶇О
+     */
+    @Excel(name = "瀛樺叆minio鏃剁殑鏂囦欢鍚嶇О")
+    @ApiModelProperty(value = "瀛樺叆minio鏃剁殑鏂囦欢鍚嶇О")
+    private String fileName;
+
+    /**
+     * 鏂囦欢鐨刢ontent-type
+     */
+    @Excel(name = "鏂囦欢鐨刢ontent-type")
+    @ApiModelProperty(value = "鏂囦欢鐨刢ontent-type")
+    private String mime;
+
+    /**
+     * 鏂囦欢璺緞
+     */
+    @Excel(name = "鏂囦欢璺緞")
+    @ApiModelProperty(value = "鏂囦欢璺緞")
+    private String fileUrl;
+
+    /**
+     * 鏄惁鍒犻櫎 0 鍚� 1 鏄�
+     */
+    @Excel(name = "鏄惁鍒犻櫎 0 鍚� 1 鏄�")
+    @ApiModelProperty(value = "鏄惁鍒犻櫎 0 鍚� 1 鏄�")
+    private Integer isDelete;
+
+}
diff --git a/smartor/src/main/java/com/smartor/domain/MinioResponseDTO.java b/smartor/src/main/java/com/smartor/domain/MinioResponseDTO.java
new file mode 100644
index 0000000..74b0a44
--- /dev/null
+++ b/smartor/src/main/java/com/smartor/domain/MinioResponseDTO.java
@@ -0,0 +1,15 @@
+package com.smartor.domain;
+
+import io.swagger.annotations.ApiModel;
+import lombok.Data;
+
+@Data
+@ApiModel(value = "MinioResponseDTO", description = "鏍囩鍒嗙被瀵硅薄")
+public class MinioResponseDTO {
+    private Long fileId;
+
+    private String fileUrl;
+
+    private String originalFileName;
+
+}
diff --git a/smartor/src/main/java/com/smartor/domain/PatArchiveReq.java b/smartor/src/main/java/com/smartor/domain/PatArchiveReq.java
index b0c86f9..598079a 100644
--- a/smartor/src/main/java/com/smartor/domain/PatArchiveReq.java
+++ b/smartor/src/main/java/com/smartor/domain/PatArchiveReq.java
@@ -48,7 +48,7 @@
      * 鏍囩ID
      */
     @ApiModelProperty("鏍囩ID")
-    private String tagId;
+    private List<String> tagIds;
 
 
 }
diff --git a/smartor/src/main/java/com/smartor/domain/TreeNode.java b/smartor/src/main/java/com/smartor/domain/TreeNode.java
new file mode 100644
index 0000000..047ca30
--- /dev/null
+++ b/smartor/src/main/java/com/smartor/domain/TreeNode.java
@@ -0,0 +1,31 @@
+package com.smartor.domain;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import org.apache.commons.lang3.ObjectUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+
+@ApiModel(value = "TreeNode", description = "鑺傜偣鏍�")
+@Data
+public class TreeNode {
+    @ApiModelProperty(name = "鑺傜偣鍚嶇О")
+    private String name;
+
+    @ApiModelProperty(name = "瀛愯妭鐐归泦鍚�")
+    private List<TreeNode> children;
+
+    public TreeNode(String name) {
+        this.name = name;
+        this.children = new ArrayList<>();
+    }
+
+    public void addChild(TreeNode child) {
+            children.add(child);
+
+    }
+
+
+}
diff --git a/smartor/src/main/java/com/smartor/mapper/MinioFileMapper.java b/smartor/src/main/java/com/smartor/mapper/MinioFileMapper.java
new file mode 100644
index 0000000..0558bf9
--- /dev/null
+++ b/smartor/src/main/java/com/smartor/mapper/MinioFileMapper.java
@@ -0,0 +1,63 @@
+package com.smartor.mapper;
+
+import com.smartor.domain.MinioFile;
+import org.apache.ibatis.annotations.Mapper;
+
+import java.util.List;
+
+/**
+ * 銆愯濉啓鍔熻兘鍚嶇О銆慚apper鎺ュ彛
+ *
+ * @author ruoyi
+ * @date 2023-06-19
+ */
+@Mapper
+public interface MinioFileMapper {
+    /**
+     * 鏌ヨ銆愯濉啓鍔熻兘鍚嶇О銆�
+     *
+     * @param id 銆愯濉啓鍔熻兘鍚嶇О銆戜富閿�
+     * @return 銆愯濉啓鍔熻兘鍚嶇О銆�
+     */
+    public MinioFile selectMinioFileById(Long id);
+
+    /**
+     * 鏌ヨ銆愯濉啓鍔熻兘鍚嶇О銆戝垪琛�
+     *
+     * @param minioFile 銆愯濉啓鍔熻兘鍚嶇О銆�
+     * @return 銆愯濉啓鍔熻兘鍚嶇О銆戦泦鍚�
+     */
+    public List<MinioFile> selectMinioFileList(MinioFile minioFile);
+
+    /**
+     * 鏂板銆愯濉啓鍔熻兘鍚嶇О銆�
+     *
+     * @param minioFile 銆愯濉啓鍔熻兘鍚嶇О銆�
+     * @return 缁撴灉
+     */
+    public int insertMinioFile(MinioFile minioFile);
+
+    /**
+     * 淇敼銆愯濉啓鍔熻兘鍚嶇О銆�
+     *
+     * @param minioFile 銆愯濉啓鍔熻兘鍚嶇О銆�
+     * @return 缁撴灉
+     */
+    public int updateMinioFile(MinioFile minioFile);
+
+    /**
+     * 鍒犻櫎銆愯濉啓鍔熻兘鍚嶇О銆�
+     *
+     * @param id 銆愯濉啓鍔熻兘鍚嶇О銆戜富閿�
+     * @return 缁撴灉
+     */
+    public int deleteMinioFileById(Long id);
+
+    /**
+     * 鎵归噺鍒犻櫎銆愯濉啓鍔熻兘鍚嶇О銆�
+     *
+     * @param ids 闇�瑕佸垹闄ょ殑鏁版嵁涓婚敭闆嗗悎
+     * @return 缁撴灉
+     */
+    public int deleteMinioFileByIds(Long[] ids);
+}
diff --git a/smartor/src/main/java/com/smartor/service/IMinioFileService.java b/smartor/src/main/java/com/smartor/service/IMinioFileService.java
new file mode 100644
index 0000000..4eb2a6f
--- /dev/null
+++ b/smartor/src/main/java/com/smartor/service/IMinioFileService.java
@@ -0,0 +1,96 @@
+package com.smartor.service;
+
+import com.smartor.domain.MinioFile;
+import com.smartor.domain.MinioResponseDTO;
+import com.smartor.domain.TreeNode;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.InputStream;
+import java.util.List;
+
+/**
+ * 銆愯濉啓鍔熻兘鍚嶇О銆慡ervice鎺ュ彛
+ *
+ * @author ruoyi
+ * @date 2023-06-19
+ */
+public interface IMinioFileService {
+    /**
+     * 鏌ヨ銆愯濉啓鍔熻兘鍚嶇О銆�
+     *
+     * @param id 銆愯濉啓鍔熻兘鍚嶇О銆戜富閿�
+     * @return 銆愯濉啓鍔熻兘鍚嶇О銆�
+     */
+    public MinioFile selectMinioFileById(Long id);
+
+    /**
+     * 鏌ヨ銆愯濉啓鍔熻兘鍚嶇О銆戝垪琛�
+     *
+     * @param minioFile 銆愯濉啓鍔熻兘鍚嶇О銆�
+     * @return 銆愯濉啓鍔熻兘鍚嶇О銆戦泦鍚�
+     */
+    public List<MinioFile> selectMinioFileList(MinioFile minioFile);
+
+    /**
+     * 鏂板銆愯濉啓鍔熻兘鍚嶇О銆�
+     *
+     * @param minioFile 銆愯濉啓鍔熻兘鍚嶇О銆�
+     * @return 缁撴灉
+     */
+    public int insertMinioFile(MinioFile minioFile);
+
+    /**
+     * 淇敼銆愯濉啓鍔熻兘鍚嶇О銆�
+     *
+     * @param minioFile 銆愯濉啓鍔熻兘鍚嶇О銆�
+     * @return 缁撴灉
+     */
+    public int updateMinioFile(MinioFile minioFile);
+
+    /**
+     * 鎵归噺鍒犻櫎銆愯濉啓鍔熻兘鍚嶇О銆�
+     *
+     * @param ids 闇�瑕佸垹闄ょ殑銆愯濉啓鍔熻兘鍚嶇О銆戜富閿泦鍚�
+     * @return 缁撴灉
+     */
+    public int deleteMinioFileByIds(Long[] ids);
+
+    /**
+     * 鍒犻櫎銆愯濉啓鍔熻兘鍚嶇О銆戜俊鎭�
+     *
+     * @param id 銆愯濉啓鍔熻兘鍚嶇О銆戜富閿�
+     * @return 缁撴灉
+     */
+    public int deleteMinioFileById(Long id);
+
+    /**
+     * 鏂囦欢鎵归噺涓婁紶
+     *
+     * @param files
+     * @return
+     */
+    public List<MinioResponseDTO> commonUploadFile(String path, List<MultipartFile> files);
+
+    /**
+     * 鑾峰彇锛堝鏁欙級寮曠敤妯℃澘
+     *
+     * @param
+     * @return
+     */
+    public TreeNode getEduTemplage();
+
+    /**
+     * @param fileName 鍏ㄨ矾寰勬枃浠跺悕
+     * @return
+     */
+    public void downloadFile(HttpServletResponse response, String fileName);
+
+    /**
+     * 鑾峰彇鍥剧墖銆侀煶棰戙�佽棰� 鐨刄RL, 鍏ュ弬鐨刦ileName涓哄叏璺緞鏂囦欢鍚�
+     *
+     * @param fileName
+     * @return
+     */
+    public String getFileUrl(String fileName, Integer expires);
+}
diff --git a/smartor/src/main/java/com/smartor/service/impl/MinioFileServiceImpl.java b/smartor/src/main/java/com/smartor/service/impl/MinioFileServiceImpl.java
new file mode 100644
index 0000000..18b54f1
--- /dev/null
+++ b/smartor/src/main/java/com/smartor/service/impl/MinioFileServiceImpl.java
@@ -0,0 +1,246 @@
+package com.smartor.service.impl;
+
+import cn.hutool.core.io.FileUtil;
+import com.ruoyi.common.config.MinioConfig;
+import com.ruoyi.common.utils.DateUtils;
+import com.ruoyi.common.utils.MinioClientUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.smartor.domain.MinioFile;
+import com.smartor.domain.MinioResponseDTO;
+import com.smartor.domain.TreeNode;
+import com.smartor.mapper.MinioFileMapper;
+import com.smartor.service.IMinioFileService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.RandomStringUtils;
+import org.apache.commons.lang3.math.NumberUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+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.time.Instant;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 銆愯濉啓鍔熻兘鍚嶇О銆慡ervice涓氬姟灞傚鐞�
+ *
+ * @author ruoyi
+ * @date 2023-06-19
+ */
+@Slf4j
+@Service
+public class MinioFileServiceImpl implements IMinioFileService {
+    @Autowired
+    private MinioFileMapper minioFileMapper;
+
+    @Resource
+    private MinioClientUtils minioClientUtils;
+    @Resource
+    private MinioConfig minioConfig;
+
+    /**
+     * 鏌ヨ銆愯濉啓鍔熻兘鍚嶇О銆�
+     *
+     * @param id 銆愯濉啓鍔熻兘鍚嶇О銆戜富閿�
+     * @return 銆愯濉啓鍔熻兘鍚嶇О銆�
+     */
+    @Override
+    public MinioFile selectMinioFileById(Long id) {
+        return minioFileMapper.selectMinioFileById(id);
+    }
+
+    /**
+     * 鏌ヨ銆愯濉啓鍔熻兘鍚嶇О銆戝垪琛�
+     *
+     * @param minioFile 銆愯濉啓鍔熻兘鍚嶇О銆�
+     * @return 銆愯濉啓鍔熻兘鍚嶇О銆�
+     */
+    @Override
+    public List<MinioFile> selectMinioFileList(MinioFile minioFile) {
+        return minioFileMapper.selectMinioFileList(minioFile);
+    }
+
+    /**
+     * 鏂板銆愯濉啓鍔熻兘鍚嶇О銆�
+     *
+     * @param minioFile 銆愯濉啓鍔熻兘鍚嶇О銆�
+     * @return 缁撴灉
+     */
+    @Override
+    public int insertMinioFile(MinioFile minioFile) {
+        minioFile.setCreateTime(DateUtils.getNowDate());
+        return minioFileMapper.insertMinioFile(minioFile);
+    }
+
+    /**
+     * 淇敼銆愯濉啓鍔熻兘鍚嶇О銆�
+     *
+     * @param minioFile 銆愯濉啓鍔熻兘鍚嶇О銆�
+     * @return 缁撴灉
+     */
+    @Override
+    public int updateMinioFile(MinioFile minioFile) {
+        minioFile.setUpdateTime(DateUtils.getNowDate());
+        return minioFileMapper.updateMinioFile(minioFile);
+    }
+
+    /**
+     * 鎵归噺鍒犻櫎銆愯濉啓鍔熻兘鍚嶇О銆�
+     *
+     * @param ids 闇�瑕佸垹闄ょ殑銆愯濉啓鍔熻兘鍚嶇О銆戜富閿�
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteMinioFileByIds(Long[] ids) {
+        return minioFileMapper.deleteMinioFileByIds(ids);
+    }
+
+    /**
+     * 鍒犻櫎銆愯濉啓鍔熻兘鍚嶇О銆戜俊鎭�
+     *
+     * @param id 銆愯濉啓鍔熻兘鍚嶇О銆戜富閿�
+     * @return 缁撴灉
+     */
+    @Override
+    public int deleteMinioFileById(Long id) {
+        return minioFileMapper.deleteMinioFileById(id);
+    }
+
+    @Override
+    public List<MinioResponseDTO> commonUploadFile(String path, List<MultipartFile> files) {
+        log.info(files.toString());
+        if (StringUtils.isNotEmpty(path) && !path.endsWith("/")) {
+            path = path + "/";
+        }
+
+        List<MinioResponseDTO> MinioResponseDTOList = new ArrayList<>();
+        for (MultipartFile file : files) {
+            String originalFilename = file.getOriginalFilename();
+//            鑾峰彇鏂囦欢鎷撳睍鍚�
+            String extName = FileUtil.extName(originalFilename);
+            log.info("鏂囦欢鎷撳睍鍚�:" + extName);
+//            鐢熸垚鏂扮殑鏂囦欢鍚嶏紝瀛樺叆鍒癿inio
+            long millSeconds = Instant.now().toEpochMilli();
+            String minioFileName = millSeconds + RandomStringUtils.randomNumeric(12) + "." + extName;
+            String contentType = file.getContentType();
+            log.info("鏂囦欢mime:{}", contentType);
+//            杩斿洖鏂囦欢澶у皬,鍗曚綅瀛楄妭
+            long size = file.getSize();
+            log.info("鏂囦欢澶у皬锛�" + size);
+            try {
+                String bucketName = minioConfig.getBucketName();
+                minioClientUtils.putObject(bucketName, file, path + originalFilename);
+//                String fileUrl = minioClientUtils.getObjectUrl(bucketName, path + originalFilename);
+                String fileUrl = path + originalFilename;
+                MinioFile minioFile = new MinioFile();
+                minioFile.setOriginalFileName(originalFilename);
+                minioFile.setFileExtName(extName);
+                minioFile.setFileName(originalFilename);
+                minioFile.setFileSize(size);
+                minioFile.setMime(contentType);
+                minioFile.setIsDelete(NumberUtils.INTEGER_ZERO);
+                minioFile.setFileUrl(fileUrl);
+                int i = insertMinioFile(minioFile);
+                if (i > 0) {
+                    MinioResponseDTO minioResponseDTO = new MinioResponseDTO();
+                    minioResponseDTO.setFileId(minioFile.getId());
+                    minioResponseDTO.setOriginalFileName(originalFilename);
+                    minioResponseDTO.setFileUrl(fileUrl);
+                    MinioResponseDTOList.add(minioResponseDTO);
+                }
+
+
+            } catch (Exception e) {
+                log.error("涓婁紶鏂囦欢鍑洪敊:{}", e);
+
+            }
+        }
+        return MinioResponseDTOList;
+    }
+
+    @Override
+    public TreeNode getEduTemplage() {
+        List<MinioFile> minioFiles = minioFileMapper.selectMinioFileList(null);
+
+        TreeNode root = new TreeNode("");
+        // 浣跨敤閫掑綊灏嗗垪琛ㄨ浆鎴愭爲寮�缁撴瀯
+        for (MinioFile minioFile1 : minioFiles) {
+            String[] parts = minioFile1.getFileUrl().split("/");
+            TreeNode current = root;
+            for (String part : parts) {
+                if (!part.isEmpty()) {
+                    TreeNode child = findChild(current, part);
+                    if (child == null) {
+                        child = new TreeNode(part);
+                        current.addChild(child);
+                    }
+                    current = child;
+                }
+            }
+        }
+        return root;
+    }
+
+    @Override
+    public void downloadFile(HttpServletResponse response, String fileName) {
+        InputStream object = null;
+        try {
+            object = minioClientUtils.getObject(minioConfig.getBucketName(), fileName);
+            writeFile(response, object);
+        } catch (Exception e) {
+            log.info("鏂囦欢涓嬭浇锛屾姤閿欎簡锛侊紒锛亄}", fileName);
+            e.printStackTrace();
+        }
+    }
+
+    @Override
+    public String getFileUrl(String fileName, Integer expires) {
+        String presignedObjectUrl = null;
+        try {
+            presignedObjectUrl = minioClientUtils.getPresignedObjectUrl(minioConfig.getBucketName(), fileName, expires);
+            //鍘绘帀url閲�?鍚庨潰鐨勮姹備俊鎭�
+            presignedObjectUrl = presignedObjectUrl.substring(0, presignedObjectUrl.lastIndexOf("?"));
+        } catch (Exception e) {
+            log.info("鏂囦欢涓嬭浇锛屾姤閿欎簡锛侊紒锛亄},  {}", fileName, expires);
+            e.printStackTrace();
+        }
+        return presignedObjectUrl;
+    }
+
+    private TreeNode findChild(TreeNode parent, String name) {
+        for (TreeNode child : parent.getChildren()) {
+            if (child.getName().equals(name)) {
+                return child;
+            }
+        }
+        return null;
+    }
+
+    public void writeFile(HttpServletResponse resp, InputStream inputStream) {
+        OutputStream out = null;
+        try {
+            out = resp.getOutputStream();
+            int len = 0;
+            byte[] b = new byte[1024];
+            while ((len = inputStream.read(b)) != -1) {
+                out.write(b, 0, len);
+            }
+            out.flush();
+        } catch (IOException e) {
+            e.printStackTrace();
+        } finally {
+            try {
+                if (out != null) {
+                    out.close();
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+    }
+}
diff --git a/smartor/src/main/resources/mapper/smartor/BaseTagcategoryMapper.xml b/smartor/src/main/resources/mapper/smartor/BaseTagcategoryMapper.xml
index 99d50b3..81d2ab7 100644
--- a/smartor/src/main/resources/mapper/smartor/BaseTagcategoryMapper.xml
+++ b/smartor/src/main/resources/mapper/smartor/BaseTagcategoryMapper.xml
@@ -132,10 +132,10 @@
         a.upload_time,
         a.categoryname,
         count(b.tagid) as tagNum
-        from base_tagcategory a,base_tag b
+        from base_tagcategory a left join base_tag b
+        on a.tagcategoryid = b.tagcategoryid
         <where>
-            a.tagcategoryid = b.tagcategoryid
-            <if test="categoryname != null  and categoryname != ''">and a.categoryname like concat('%', #{categoryname},
+            <if test="categoryname != null  and categoryname != ''">a.categoryname like concat('%', #{categoryname},
                 '%')
             </if>
         </where>
diff --git a/smartor/src/main/resources/mapper/smartor/MinioFileMapper.xml b/smartor/src/main/resources/mapper/smartor/MinioFileMapper.xml
new file mode 100644
index 0000000..1f6c32e
--- /dev/null
+++ b/smartor/src/main/resources/mapper/smartor/MinioFileMapper.xml
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.smartor.mapper.MinioFileMapper">
+
+    <resultMap type="com.smartor.domain.MinioFile" id="MinioFileResult">
+        <result property="id" column="id"/>
+        <result property="originalFileName" column="original_file_name"/>
+        <result property="fileExtName" column="file_ext_name"/>
+        <result property="fileSize" column="file_size"/>
+        <result property="fileName" column="file_name"/>
+        <result property="mime" column="mime"/>
+        <result property="fileUrl" column="file_url"/>
+        <result property="isDelete" column="is_delete"/>
+        <result property="createBy" column="create_by"/>
+        <result property="createTime" column="create_time"/>
+        <result property="updateBy" column="update_by"/>
+        <result property="updateTime" column="update_time"/>
+    </resultMap>
+
+    <sql id="selectMinioFileVo">
+        select id,
+               original_file_name,
+               file_ext_name,
+               file_size,
+               file_name,
+               mime,
+               file_url,
+               is_delete,
+               create_by,
+               create_time,
+               update_by,
+               update_time
+        from minio_file
+    </sql>
+
+    <select id="selectMinioFileList" parameterType="com.smartor.domain.MinioFile" resultMap="MinioFileResult">
+        <include refid="selectMinioFileVo"/>
+        <where>
+            <if test="originalFileName != null  and originalFileName != ''">and original_file_name like concat('%',
+                #{originalFileName}, '%')
+            </if>
+            <if test="fileExtName != null  and fileExtName != ''">and file_ext_name like concat('%', #{fileExtName},
+                '%')
+            </if>
+            <if test="fileSize != null ">and file_size = #{fileSize}</if>
+            <if test="fileName != null  and fileName != ''">and file_name like concat('%', #{fileName}, '%')</if>
+            <if test="mime != null  and mime != ''">and mime = #{mime}</if>
+            <if test="fileUrl != null  and fileUrl != ''">and file_url = #{fileUrl}</if>
+            <if test="isDelete != null ">and is_delete = #{isDelete}</if>
+        </where>
+    </select>
+
+    <select id="selectMinioFileById" parameterType="Long" resultMap="MinioFileResult">
+        <include refid="selectMinioFileVo"/>
+        where id = #{id}
+    </select>
+
+    <insert id="insertMinioFile" parameterType="com.smartor.domain.MinioFile">
+        insert into minio_file
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="id != null">id,</if>
+            <if test="originalFileName != null">original_file_name,</if>
+            <if test="fileExtName != null">file_ext_name,</if>
+            <if test="fileSize != null">file_size,</if>
+            <if test="fileName != null">file_name,</if>
+            <if test="mime != null">mime,</if>
+            <if test="fileUrl != null">file_url,</if>
+            <if test="isDelete != null">is_delete,</if>
+            <if test="createBy != null">create_by,</if>
+            <if test="createTime != null">create_time,</if>
+            <if test="updateBy != null">update_by,</if>
+            <if test="updateTime != null">update_time,</if>
+        </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="id != null">#{id},</if>
+            <if test="originalFileName != null">#{originalFileName},</if>
+            <if test="fileExtName != null">#{fileExtName},</if>
+            <if test="fileSize != null">#{fileSize},</if>
+            <if test="fileName != null">#{fileName},</if>
+            <if test="mime != null">#{mime},</if>
+            <if test="fileUrl != null">#{fileUrl},</if>
+            <if test="isDelete != null">#{isDelete},</if>
+            <if test="createBy != null">#{createBy},</if>
+            <if test="createTime != null">#{createTime},</if>
+            <if test="updateBy != null">#{updateBy},</if>
+            <if test="updateTime != null">#{updateTime},</if>
+        </trim>
+    </insert>
+
+    <update id="updateMinioFile" parameterType="com.smartor.domain.MinioFile">
+        update minio_file
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="originalFileName != null">original_file_name = #{originalFileName},</if>
+            <if test="fileExtName != null">file_ext_name = #{fileExtName},</if>
+            <if test="fileSize != null">file_size = #{fileSize},</if>
+            <if test="fileName != null">file_name = #{fileName},</if>
+            <if test="mime != null">mime = #{mime},</if>
+            <if test="fileUrl != null">file_url = #{fileUrl},</if>
+            <if test="isDelete != null">is_delete = #{isDelete},</if>
+            <if test="createBy != null">create_by = #{createBy},</if>
+            <if test="createTime != null">create_time = #{createTime},</if>
+            <if test="updateBy != null">update_by = #{updateBy},</if>
+            <if test="updateTime != null">update_time = #{updateTime},</if>
+        </trim>
+        where id = #{id}
+    </update>
+
+    <delete id="deleteMinioFileById" parameterType="Long">
+        delete
+        from minio_file
+        where id = #{id}
+    </delete>
+
+    <delete id="deleteMinioFileByIds" parameterType="String">
+        delete from minio_file where id in
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+</mapper>
\ No newline at end of file
diff --git a/smartor/src/main/resources/mapper/smartor/PatArchiveMapper.xml b/smartor/src/main/resources/mapper/smartor/PatArchiveMapper.xml
index 400feeb..1cc1517 100644
--- a/smartor/src/main/resources/mapper/smartor/PatArchiveMapper.xml
+++ b/smartor/src/main/resources/mapper/smartor/PatArchiveMapper.xml
@@ -88,7 +88,11 @@
             <if test="name != null  and name != ''">and a.name like concat('%', #{name}, '%')</if>
             <if test="iccardno != null  and iccardno != ''">and iccardno = #{iccardno}</if>
             <if test="telcode != null  and telcode != ''">and telcode = #{telcode}</if>
-            <if test="tagId != null  and tagId != ''">and c.tagid = #{tagId}</if>
+            <if test="tagIds != null  and tagIds != ''">and c.tagid in
+                <foreach collection="tagIds" item="tagId" open="(" separator="," close=")">
+                    #{tagId}
+                </foreach>
+            </if>
         </where>
     </select>
 
@@ -97,7 +101,8 @@
         where patid = #{patid}
     </select>
 
-    <insert id="insertPatArchive" parameterType="com.smartor.domain.PatArchive" useGeneratedKeys="true" keyProperty="patid">
+    <insert id="insertPatArchive" parameterType="com.smartor.domain.PatArchive" useGeneratedKeys="true"
+            keyProperty="patid">
         insert into pat_archive
         <trim prefix="(" suffix=")" suffixOverrides=",">
             <if test="name != null">name,</if>

--
Gitblit v1.9.3