Bladeren bron

【ADD】增加文件服务器配置

ZhaoMn 4 jaren geleden
bovenliggende
commit
f0d1042c6f
18 gewijzigde bestanden met toevoegingen van 372 en 205 verwijderingen
  1. 16 0
      pom.xml
  2. 12 9
      railway-admin/src/main/java/com/railway/web/controller/business/catenary/BusJcbFdfxjyqController.java
  3. 12 71
      railway-admin/src/main/java/com/railway/web/controller/common/CommonController.java
  4. 6 6
      railway-admin/src/main/java/com/railway/web/controller/system/SysProfileController.java
  5. 19 2
      railway-admin/src/main/resources/application.yml
  6. 0 36
      railway-common/src/main/java/com/railway/common/config/RailwayConfig.java
  7. 1 1
      railway-common/src/main/java/com/railway/common/config/ServerConfig.java
  8. 9 40
      railway-common/src/main/java/com/railway/common/utils/file/FileUploadUtils.java
  9. 56 14
      railway-common/src/main/java/com/railway/common/utils/file/FileUtils.java
  10. 8 23
      railway-common/src/main/java/com/railway/common/utils/file/ImageUtils.java
  11. 8 2
      railway-common/src/main/java/com/railway/common/utils/poi/ExcelUtil.java
  12. 9 1
      railway-framework/src/main/java/com/railway/framework/config/ResourcesConfig.java
  13. 18 0
      railway-system/pom.xml
  14. 43 0
      railway-system/src/main/java/com/railway/system/domain/MinioConfig.java
  15. 20 0
      railway-system/src/main/java/com/railway/system/service/ISysFileService.java
  16. 44 0
      railway-system/src/main/java/com/railway/system/service/impl/FastDfsSysFileServiceImpl.java
  17. 45 0
      railway-system/src/main/java/com/railway/system/service/impl/LocalSysFileServiceImpl.java
  18. 46 0
      railway-system/src/main/java/com/railway/system/service/impl/MinioSysFileServiceImpl.java

+ 16 - 0
pom.xml

@@ -43,6 +43,8 @@
     <velocity.version>1.7</velocity.version>
     <lombok.version>1.18.6</lombok.version>
     <jwt.version>0.9.1</jwt.version>
+    <tobato.version>1.27.2</tobato.version>
+    <minio.version>8.2.2</minio.version>
   </properties>
 
   <!-- 依赖声明 -->
@@ -139,6 +141,20 @@
         <version>${commons.fileupload.version}</version>
       </dependency>
 
+      <!-- FastDFS 分布式文件系统 -->
+      <dependency>
+        <groupId>com.github.tobato</groupId>
+        <artifactId>fastdfs-client</artifactId>
+        <version>${tobato.version}</version>
+      </dependency>
+
+      <!-- Minio -->
+      <dependency>
+        <groupId>io.minio</groupId>
+        <artifactId>minio</artifactId>
+        <version>${minio.version}</version>
+      </dependency>
+
       <!-- excel工具 -->
       <dependency>
         <groupId>org.apache.poi</groupId>

+ 12 - 9
railway-admin/src/main/java/com/railway/web/controller/business/catenary/BusJcbFdfxjyqController.java

@@ -2,20 +2,23 @@ package com.railway.web.controller.business.catenary;
 
 import com.railway.business.catenary.domain.BusJcbFdfxjyq;
 import com.railway.business.catenary.service.IBusJcbFdfxjyqService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.ResponseEntity;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.*;
-import org.springframework.web.bind.WebDataBinder;
 import com.railway.common.core.controller.BaseController;
 import com.railway.common.core.domain.AjaxResult;
 import com.railway.common.core.page.TableDataInfo;
-import javax.validation.Valid;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
 import java.util.List;
-
 import javax.validation.Valid;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
 
 @Api(value = "rest/catenary/bus/jcb/fdfxjyq", tags = "dxf分段绝缘器检查表")
 @RestController

+ 12 - 71
railway-admin/src/main/java/com/railway/web/controller/common/CommonController.java

@@ -1,19 +1,13 @@
 package com.railway.web.controller.common;
 
-import com.railway.common.config.RailwayConfig;
-import com.railway.common.constant.Constants;
 import com.railway.common.core.domain.AjaxResult;
 import com.railway.common.utils.StringUtils;
-import com.railway.common.utils.file.FileUploadUtils;
 import com.railway.common.utils.file.FileUtils;
-import com.railway.framework.config.ServerConfig;
+import com.railway.system.service.ISysFileService;
 import io.swagger.annotations.Api;
 import java.util.ArrayList;
 import java.util.List;
-import javax.servlet.http.HttpServletResponse;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.http.MediaType;
-import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.ResponseBody;
 import org.springframework.web.bind.annotation.RestController;
@@ -29,39 +23,12 @@ import org.springframework.web.multipart.MultipartFile;
 @RestController
 public class CommonController {
 
-  private final ServerConfig serverConfig;
+  private final ISysFileService sysFileService;
 
   private static final String FILE_DELIMETER = ",";
 
-  public CommonController(ServerConfig serverConfig) {
-    this.serverConfig = serverConfig;
-  }
-
-  /**
-   * 通用下载请求
-   *
-   * @param fileName 文件名称
-   * @param delete 是否删除
-   */
-  @GetMapping("common/download")
-  public void fileDownload(String fileName, Boolean delete, HttpServletResponse response) {
-    try {
-      if (!FileUtils.checkAllowDownload(fileName)) {
-        throw new Exception(StringUtils.format("文件名称({})非法,不允许下载。 ", fileName));
-      }
-      String realFileName =
-          System.currentTimeMillis() + fileName.substring(fileName.indexOf("_") + 1);
-      String filePath = RailwayConfig.getDownloadPath() + fileName;
-
-      response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
-      FileUtils.setAttachmentResponseHeader(response, realFileName);
-      FileUtils.writeBytes(filePath, response.getOutputStream());
-      if (delete) {
-        FileUtils.deleteFile(filePath);
-      }
-    } catch (Exception e) {
-      log.error("下载文件失败", e);
-    }
+  public CommonController(ISysFileService sysFileService) {
+    this.sysFileService = sysFileService;
   }
 
   /**
@@ -71,11 +38,10 @@ public class CommonController {
   @ResponseBody
   public AjaxResult uploadFile(MultipartFile file) {
     try {
-      // 上传文件路径
-      String filePath = RailwayConfig.getUploadPath();
-      // 上传并返回新文件名称
-      String fileName = FileUploadUtils.upload(filePath, file);
-      String url = serverConfig.getUrl() + fileName;
+      // 上传并返回访问地址
+      String url = sysFileService.uploadFile(file);
+      // 新文件名称
+      String fileName = FileUtils.getName(url);
       AjaxResult ajax = AjaxResult.success();
       ajax.put("fileName", fileName);
       ajax.put("url", url);
@@ -92,14 +58,13 @@ public class CommonController {
   @ResponseBody
   public AjaxResult uploadFiles(List<MultipartFile> files) {
     try {
-      // 上传文件路径
-      String filePath = RailwayConfig.getUploadPath();
       List<String> fileNames = new ArrayList<>();
       List<String> urls = new ArrayList<>();
       for (MultipartFile file : files) {
-        // 上传并返回新文件名称
-        String fileName = FileUploadUtils.upload(filePath, file);
-        String url = serverConfig.getUrl() + fileName;
+        // 上传并返回访问地址
+        String url = sysFileService.uploadFile(file);
+        // 新文件名称
+        String fileName = FileUtils.getName(url);
         fileNames.add(fileName);
         urls.add(url);
       }
@@ -112,28 +77,4 @@ public class CommonController {
     }
   }
 
-  /**
-   * 本地资源通用下载
-   */
-  @GetMapping("/common/download/resource")
-  public void resourceDownload(String resource,
-      HttpServletResponse response) {
-    try {
-      if (!FileUtils.checkAllowDownload(resource)) {
-        throw new Exception(StringUtils.format("资源文件({})非法,不允许下载。 ", resource));
-      }
-      // 本地资源路径
-      String localPath = RailwayConfig.getProfile();
-      // 数据库资源地址
-      String downloadPath =
-          localPath + StringUtils.substringAfter(resource, Constants.RESOURCE_PREFIX);
-      // 下载名称
-      String downloadName = StringUtils.substringAfterLast(downloadPath, "/");
-      response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
-      FileUtils.setAttachmentResponseHeader(response, downloadName);
-      FileUtils.writeBytes(downloadPath, response.getOutputStream());
-    } catch (Exception e) {
-      log.error("下载文件失败", e);
-    }
-  }
 }

+ 6 - 6
railway-admin/src/main/java/com/railway/web/controller/system/SysProfileController.java

@@ -1,7 +1,6 @@
 package com.railway.web.controller.system;
 
 import com.railway.common.annotation.Log;
-import com.railway.common.config.RailwayConfig;
 import com.railway.common.constant.UserConstants;
 import com.railway.common.core.controller.BaseController;
 import com.railway.common.core.domain.AjaxResult;
@@ -10,11 +9,10 @@ import com.railway.common.core.domain.model.LoginUser;
 import com.railway.common.enums.BusinessType;
 import com.railway.common.utils.SecurityUtils;
 import com.railway.common.utils.StringUtils;
-import com.railway.common.utils.file.FileUploadUtils;
 import com.railway.framework.web.service.TokenService;
+import com.railway.system.service.ISysFileService;
 import com.railway.system.service.ISysUserService;
 import io.swagger.annotations.Api;
-import java.io.IOException;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.PutMapping;
@@ -36,11 +34,13 @@ public class SysProfileController extends BaseController {
 
   private final ISysUserService userService;
   private final TokenService tokenService;
+  private final ISysFileService sysFileService;
 
   public SysProfileController(ISysUserService userService,
-      TokenService tokenService) {
+      TokenService tokenService, ISysFileService sysFileService) {
     this.userService = userService;
     this.tokenService = tokenService;
+    this.sysFileService = sysFileService;
   }
 
   /**
@@ -115,10 +115,10 @@ public class SysProfileController extends BaseController {
    */
   @Log(title = "用户头像", businessType = BusinessType.UPDATE)
   @PostMapping("/avatar")
-  public AjaxResult avatar(@RequestParam("avatarfile") MultipartFile file) throws IOException {
+  public AjaxResult avatar(@RequestParam("avatarfile") MultipartFile file) throws Exception {
     if (!file.isEmpty()) {
       LoginUser loginUser = getLoginUser();
-      String avatar = FileUploadUtils.upload(RailwayConfig.getAvatarPath(), file);
+      String avatar = sysFileService.uploadFile(file);
       if (userService.updateUserAvatar(loginUser.getUsername(), avatar)) {
         AjaxResult ajax = AjaxResult.success();
         ajax.put("imgUrl", avatar);

+ 19 - 2
railway-admin/src/main/resources/application.yml

@@ -8,8 +8,6 @@ railway:
   copyrightYear: 2021
   # 实例演示开关
   demoEnabled: true
-  # 文件路径 示例( Windows配置D:/railway/uploadPath,Linux配置 /home/railway/uploadPath)
-  profile: D:/railway/uploadPath
   # 获取ip地址开关
   addressEnabled: false
   # 验证码类型 math 数组计算 char 字符验证
@@ -118,3 +116,22 @@ xss:
   excludes: /system/notice
   # 匹配链接
   urlPatterns: /system/*,/monitor/*,/tool/*
+
+# 本地文件上传
+file:
+  # 文件路径 示例( Windows配置D:/railway/uploadPath,Linux配置 /home/railway/uploadPath)
+  path: D:/railway/uploadPath
+
+# FastDFS配置
+fdfs:
+  domain: http://30.129.231.12
+  soTimeout: 3000
+  connectTimeout: 2000
+  trackerList: 30.129.231.12:22122
+
+# Minio配置
+minio:
+  url: http://30.129.231.12:9000
+  accessKey: minioadmin
+  secretKey: minioadmin
+  bucketName: test

+ 0 - 36
railway-common/src/main/java/com/railway/common/config/RailwayConfig.java

@@ -34,11 +34,6 @@ public class RailwayConfig {
    */
   private boolean demoEnabled;
 
-  /**
-   * 上传路径
-   */
-  private static String profile;
-
   /**
    * 获取地址开关
    */
@@ -52,35 +47,4 @@ public class RailwayConfig {
     RailwayConfig.addressEnabled = addressEnabled;
   }
 
-  public static String getProfile() {
-    return profile;
-  }
-
-  /**
-   * 获取导入上传路径
-   */
-  public static String getImportPath() {
-    return getProfile() + "/import";
-  }
-
-  /**
-   * 获取头像上传路径
-   */
-  public static String getAvatarPath() {
-    return getProfile() + "/avatar";
-  }
-
-  /**
-   * 获取下载路径
-   */
-  public static String getDownloadPath() {
-    return getProfile() + "/download/";
-  }
-
-  /**
-   * 获取上传路径
-   */
-  public static String getUploadPath() {
-    return getProfile() + "/upload";
-  }
 }

+ 1 - 1
railway-framework/src/main/java/com/railway/framework/config/ServerConfig.java → railway-common/src/main/java/com/railway/common/config/ServerConfig.java

@@ -1,4 +1,4 @@
-package com.railway.framework.config;
+package com.railway.common.config;
 
 import javax.servlet.http.HttpServletRequest;
 import org.springframework.stereotype.Component;

+ 9 - 40
railway-common/src/main/java/com/railway/common/utils/file/FileUploadUtils.java

@@ -1,18 +1,16 @@
 package com.railway.common.utils.file;
 
-import java.io.File;
-import java.io.IOException;
-import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.io.FilenameUtils;
-import org.springframework.web.multipart.MultipartFile;
-import com.railway.common.config.RailwayConfig;
-import com.railway.common.constant.Constants;
 import com.railway.common.exception.file.FileNameLengthLimitExceededException;
 import com.railway.common.exception.file.FileSizeLimitExceededException;
 import com.railway.common.exception.file.InvalidExtensionException;
 import com.railway.common.utils.DateUtils;
 import com.railway.common.utils.StringUtils;
 import com.railway.common.utils.uuid.IdUtils;
+import java.io.File;
+import java.io.IOException;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.io.FilenameUtils;
+import org.springframework.web.multipart.MultipartFile;
 
 /**
  * 文件上传工具类
@@ -32,33 +30,6 @@ public class FileUploadUtils {
    */
   public static final int DEFAULT_FILE_NAME_LENGTH = 100;
 
-  /**
-   * 默认上传的地址
-   */
-  private static String defaultBaseDir = RailwayConfig.getProfile();
-
-  public static void setDefaultBaseDir(String defaultBaseDir) {
-    FileUploadUtils.defaultBaseDir = defaultBaseDir;
-  }
-
-  public static String getDefaultBaseDir() {
-    return defaultBaseDir;
-  }
-
-  /**
-   * 以默认配置进行文件上传
-   *
-   * @param file 上传的文件
-   * @return 文件名称
-   */
-  public static String upload(MultipartFile file) throws IOException {
-    try {
-      return upload(getDefaultBaseDir(), file, MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION);
-    } catch (Exception e) {
-      throw new IOException(e.getMessage(), e);
-    }
-  }
-
   /**
    * 根据文件路径上传
    *
@@ -100,7 +71,7 @@ public class FileUploadUtils {
 
     File desc = getAbsoluteFile(baseDir, fileName);
     file.transferTo(desc);
-    return getPathFileName(baseDir, fileName);
+    return getPathFileName(fileName);
   }
 
   /**
@@ -114,7 +85,7 @@ public class FileUploadUtils {
     return fileName;
   }
 
-  public static File getAbsoluteFile(String uploadDir, String fileName) throws IOException {
+  public static File getAbsoluteFile(String uploadDir, String fileName) {
     File desc = new File(uploadDir + File.separator + fileName);
 
     if (!desc.exists()) {
@@ -125,10 +96,8 @@ public class FileUploadUtils {
     return desc;
   }
 
-  public static String getPathFileName(String uploadDir, String fileName) throws IOException {
-    int dirLastIndex = RailwayConfig.getProfile().length() + 1;
-    String currentDir = StringUtils.substring(uploadDir, dirLastIndex);
-    return Constants.RESOURCE_PREFIX + "/" + currentDir + "/" + fileName;
+  public static String getPathFileName(String fileName) {
+    return "/" + fileName;
   }
 
   /**

+ 56 - 14
railway-common/src/main/java/com/railway/common/utils/file/FileUtils.java

@@ -1,6 +1,5 @@
 package com.railway.common.utils.file;
 
-import com.railway.common.config.RailwayConfig;
 import com.railway.common.utils.DateUtils;
 import com.railway.common.utils.StringUtils;
 import com.railway.common.utils.uuid.IdUtils;
@@ -25,6 +24,16 @@ import org.apache.commons.lang3.ArrayUtils;
  */
 public class FileUtils {
 
+  /**
+   * 字符常量:斜杠 {@code '/'}
+   */
+  public static final char SLASH = '/';
+
+  /**
+   * 字符常量:反斜杠 {@code '\\'}
+   */
+  public static final char BACKSLASH = '\\';
+
   public static String FILENAME_PATTERN = "[a-zA-Z0-9_\\-\\|\\.\\u4e00-\\u9fa5]+";
 
   /**
@@ -52,17 +61,6 @@ public class FileUtils {
     }
   }
 
-  /**
-   * 写数据到文件中
-   *
-   * @param data 数据
-   * @return 目标文件
-   * @throws IOException IO异常
-   */
-  public static String writeImportBytes(byte[] data) throws IOException {
-    return writeBytes(data, RailwayConfig.getImportPath());
-  }
-
   /**
    * 写数据到文件中
    *
@@ -73,7 +71,7 @@ public class FileUtils {
    */
   public static String writeBytes(byte[] data, String uploadDir) throws IOException {
     FileOutputStream fos = null;
-    String pathName = "";
+    String pathName;
     try {
       String extension = getFileExtendName(data);
       pathName = DateUtils.datePath() + "/" + IdUtils.fastUUID() + "." + extension;
@@ -83,7 +81,7 @@ public class FileUtils {
     } finally {
       IOUtils.close(fos);
     }
-    return FileUploadUtils.getPathFileName(uploadDir, pathName);
+    return FileUploadUtils.getPathFileName(pathName);
   }
 
   /**
@@ -111,6 +109,50 @@ public class FileUtils {
     return filename.matches(FILENAME_PATTERN);
   }
 
+  /**
+   * 返回文件名
+   *
+   * @param filePath 文件
+   * @return 文件名
+   */
+  public static String getName(String filePath) {
+    if (null == filePath) {
+      return null;
+    }
+    int len = filePath.length();
+    if (0 == len) {
+      return filePath;
+    }
+    if (isFileSeparator(filePath.charAt(len - 1))) {
+      // 以分隔符结尾的去掉结尾分隔符
+      len--;
+    }
+
+    int begin = 0;
+    char c;
+    for (int i = len - 1; i > -1; i--) {
+      c = filePath.charAt(i);
+      if (isFileSeparator(c)) {
+        // 查找最后一个路径分隔符(/或者\)
+        begin = i + 1;
+        break;
+      }
+    }
+
+    return filePath.substring(begin, len);
+  }
+
+  /**
+   * 是否为Windows或者Linux(Unix)文件分隔符<br>
+   * Windows平台下分隔符为\,Linux(Unix)为/
+   *
+   * @param c 字符
+   * @return 是否为Windows或者Linux(Unix)文件分隔符
+   */
+  public static boolean isFileSeparator(char c) {
+    return SLASH == c || BACKSLASH == c;
+  }
+
   /**
    * 检查文件是否可下载
    *

+ 8 - 23
railway-common/src/main/java/com/railway/common/utils/file/ImageUtils.java

@@ -1,11 +1,6 @@
 package com.railway.common.utils.file;
 
-import com.railway.common.config.RailwayConfig;
-import com.railway.common.constant.Constants;
-import com.railway.common.utils.StringUtils;
 import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.FileInputStream;
 import java.io.InputStream;
 import java.net.URL;
 import java.net.URLConnection;
@@ -22,7 +17,7 @@ import org.apache.poi.util.IOUtils;
 public class ImageUtils {
 
   public static byte[] getImage(String imagePath) {
-    try (InputStream is = getFile(imagePath)){
+    try (InputStream is = getFile(imagePath)) {
       assert is != null;
       return IOUtils.toByteArray(is);
     } catch (Exception e) {
@@ -50,30 +45,20 @@ public class ImageUtils {
    */
   public static byte[] readFile(String url) {
     InputStream in = null;
-    ByteArrayOutputStream baos = null;
     try {
-      if (url.startsWith("http")) {
-        // 网络地址
-        URL urlObj = new URL(url);
-        URLConnection urlConnection = urlObj.openConnection();
-        urlConnection.setConnectTimeout(30 * 1000);
-        urlConnection.setReadTimeout(60 * 1000);
-        urlConnection.setDoInput(true);
-        in = urlConnection.getInputStream();
-      } else {
-        // 本机地址
-        String localPath = RailwayConfig.getProfile();
-        String downloadPath =
-            localPath + StringUtils.substringAfter(url, Constants.RESOURCE_PREFIX);
-        in = new FileInputStream(downloadPath);
-      }
+      // 网络地址
+      URL urlObj = new URL(url);
+      URLConnection urlConnection = urlObj.openConnection();
+      urlConnection.setConnectTimeout(30 * 1000);
+      urlConnection.setReadTimeout(60 * 1000);
+      urlConnection.setDoInput(true);
+      in = urlConnection.getInputStream();
       return IOUtils.toByteArray(in);
     } catch (Exception e) {
       log.error("获取文件路径异常 {}", e.getMessage());
       return null;
     } finally {
       IOUtils.closeQuietly(in);
-      IOUtils.closeQuietly(baos);
     }
   }
 }

+ 8 - 2
railway-common/src/main/java/com/railway/common/utils/poi/ExcelUtil.java

@@ -4,7 +4,6 @@ import com.railway.common.annotation.Excel;
 import com.railway.common.annotation.Excel.ColumnType;
 import com.railway.common.annotation.Excel.Type;
 import com.railway.common.annotation.Excels;
-import com.railway.common.config.RailwayConfig;
 import com.railway.common.core.domain.AjaxResult;
 import com.railway.common.core.text.Convert;
 import com.railway.common.exception.UtilException;
@@ -73,6 +72,7 @@ import org.apache.poi.xssf.usermodel.XSSFPicture;
 import org.apache.poi.xssf.usermodel.XSSFShape;
 import org.apache.poi.xssf.usermodel.XSSFSheet;
 import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTMarker;
+import org.springframework.beans.factory.annotation.Value;
 
 /**
  * Excel相关处理
@@ -82,6 +82,12 @@ import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTMarker;
 @Slf4j
 public class ExcelUtil<T> {
 
+  /**
+   * 上传文件存储在本地的根路径
+   */
+  @Value("${file.path}")
+  private String localFilePath;
+
   /**
    * Excel sheet最大行数,默认65536
    */
@@ -907,7 +913,7 @@ public class ExcelUtil<T> {
    * @param filename 文件名称
    */
   public String getAbsoluteFile(String filename) {
-    String downloadPath = RailwayConfig.getDownloadPath() + filename;
+    String downloadPath = localFilePath + File.separator + filename;
     File desc = new File(downloadPath);
     if (!desc.getParentFile().exists()) {
       desc.getParentFile().mkdirs();

+ 9 - 1
railway-framework/src/main/java/com/railway/framework/config/ResourcesConfig.java

@@ -3,6 +3,8 @@ package com.railway.framework.config;
 import com.railway.common.config.RailwayConfig;
 import com.railway.common.constant.Constants;
 import com.railway.framework.interceptor.RepeatSubmitInterceptor;
+import java.io.File;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.web.cors.CorsConfiguration;
@@ -20,6 +22,12 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
 @Configuration
 public class ResourcesConfig implements WebMvcConfigurer {
 
+  /**
+   * 上传文件存储在本地的根路径
+   */
+  @Value("${file.path}")
+  private String localFilePath;
+
   private final RepeatSubmitInterceptor repeatSubmitInterceptor;
 
   public ResourcesConfig(
@@ -31,7 +39,7 @@ public class ResourcesConfig implements WebMvcConfigurer {
   public void addResourceHandlers(ResourceHandlerRegistry registry) {
     /* 本地文件上传路径 */
     registry.addResourceHandler(Constants.RESOURCE_PREFIX + "/**")
-        .addResourceLocations("file:" + RailwayConfig.getProfile() + "/");
+        .addResourceLocations("file:" + localFilePath + "/");
 
     /* swagger配置 */
     registry.addResourceHandler("/swagger-ui/**")

+ 18 - 0
railway-system/pom.xml

@@ -26,6 +26,24 @@
       <artifactId>lombok</artifactId>
     </dependency>
 
+    <!-- 文件上传工具类 -->
+    <dependency>
+      <groupId>commons-fileupload</groupId>
+      <artifactId>commons-fileupload</artifactId>
+    </dependency>
+
+    <!-- FastDFS 分布式文件系统 -->
+    <dependency>
+      <groupId>com.github.tobato</groupId>
+      <artifactId>fastdfs-client</artifactId>
+    </dependency>
+
+    <!-- Minio -->
+    <dependency>
+      <groupId>io.minio</groupId>
+      <artifactId>minio</artifactId>
+    </dependency>
+
   </dependencies>
 
 </project>

+ 43 - 0
railway-system/src/main/java/com/railway/system/domain/MinioConfig.java

@@ -0,0 +1,43 @@
+package com.railway.system.domain;
+
+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;
+
+/**
+ * Minio 配置信息
+ *
+ * @author ruoyi
+ */
+@Data
+@Configuration
+@ConfigurationProperties(prefix = "minio")
+public class MinioConfig {
+
+  /**
+   * 服务地址
+   */
+  private String url;
+
+  /**
+   * 用户名
+   */
+  private String accessKey;
+
+  /**
+   * 密码
+   */
+  private String secretKey;
+
+  /**
+   * 存储桶名称
+   */
+  private String bucketName;
+
+  @Bean
+  public MinioClient getMinioClient() {
+    return MinioClient.builder().endpoint(url).credentials(accessKey, secretKey).build();
+  }
+}

+ 20 - 0
railway-system/src/main/java/com/railway/system/service/ISysFileService.java

@@ -0,0 +1,20 @@
+package com.railway.system.service;
+
+import org.springframework.web.multipart.MultipartFile;
+
+/**
+ * 文件上传接口
+ * 实现类上加注解@Primary:自动装配时,被注解为@Primary的Bean将作为首选者,否则将抛出异常。(只对接口的多个实现生效)
+ * @author railway
+ */
+public interface ISysFileService
+{
+    /**
+     * 文件上传接口
+     * 
+     * @param file 上传的文件
+     * @return 访问地址
+     * @throws Exception 文件上传异常
+     */
+    String uploadFile(MultipartFile file) throws Exception;
+}

+ 44 - 0
railway-system/src/main/java/com/railway/system/service/impl/FastDfsSysFileServiceImpl.java

@@ -0,0 +1,44 @@
+package com.railway.system.service.impl;
+
+import com.github.tobato.fastdfs.domain.fdfs.StorePath;
+import com.github.tobato.fastdfs.service.FastFileStorageClient;
+import com.railway.system.service.ISysFileService;
+import org.apache.commons.io.FilenameUtils;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
+
+/**
+ * FastDFS 文件存储
+ * 
+ * @author railway
+ */
+@Service
+public class FastDfsSysFileServiceImpl implements ISysFileService {
+    /**
+     * 域名或本机访问地址
+     */
+    @Value("${fdfs.domain}")
+    public String domain;
+
+    private final FastFileStorageClient storageClient;
+
+    public FastDfsSysFileServiceImpl(FastFileStorageClient storageClient) {
+        this.storageClient = storageClient;
+    }
+
+    /**
+     * FastDfs文件上传接口
+     * 
+     * @param file 上传的文件
+     * @return 访问地址
+     * @throws Exception 文件上传异常
+     */
+    @Override
+    public String uploadFile(MultipartFile file) throws Exception
+    {
+        StorePath storePath = storageClient.uploadFile(file.getInputStream(), file.getSize(),
+                FilenameUtils.getExtension(file.getOriginalFilename()), null);
+        return domain + "/" + storePath.getFullPath();
+    }
+}

+ 45 - 0
railway-system/src/main/java/com/railway/system/service/impl/LocalSysFileServiceImpl.java

@@ -0,0 +1,45 @@
+package com.railway.system.service.impl;
+
+import com.railway.common.config.ServerConfig;
+import com.railway.common.constant.Constants;
+import com.railway.common.utils.file.FileUploadUtils;
+import com.railway.system.service.ISysFileService;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Primary;
+import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
+
+/**
+ * 本地文件存储
+ *
+ * @author railway
+ */
+@Primary
+@Service
+public class LocalSysFileServiceImpl implements ISysFileService {
+
+  /**
+   * 上传文件存储在本地的根路径
+   */
+  @Value("${file.path}")
+  private String localFilePath;
+
+  private final ServerConfig serverConfig;
+
+  public LocalSysFileServiceImpl(ServerConfig serverConfig) {
+    this.serverConfig = serverConfig;
+  }
+
+  /**
+   * 本地文件上传接口
+   *
+   * @param file 上传的文件
+   * @return 访问地址
+   * @throws Exception 文件上传异常
+   */
+  @Override
+  public String uploadFile(MultipartFile file) throws Exception {
+    String name = FileUploadUtils.upload(localFilePath, file);
+    return serverConfig.getUrl() + Constants.RESOURCE_PREFIX + name;
+  }
+}

+ 46 - 0
railway-system/src/main/java/com/railway/system/service/impl/MinioSysFileServiceImpl.java

@@ -0,0 +1,46 @@
+package com.railway.system.service.impl;
+
+import com.railway.common.utils.file.FileUploadUtils;
+import com.railway.system.domain.MinioConfig;
+import com.railway.system.service.ISysFileService;
+import io.minio.MinioClient;
+import io.minio.PutObjectArgs;
+import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
+
+/**
+ * Minio 文件存储
+ *
+ * @author railway
+ */
+@Service
+public class MinioSysFileServiceImpl implements ISysFileService {
+
+  private final MinioConfig minioConfig;
+  private final MinioClient client;
+
+  public MinioSysFileServiceImpl(MinioConfig minioConfig, MinioClient client) {
+    this.minioConfig = minioConfig;
+    this.client = client;
+  }
+
+  /**
+   * 本地文件上传接口
+   *
+   * @param file 上传的文件
+   * @return 访问地址
+   * @throws Exception 文件上传异常
+   */
+  @Override
+  public String uploadFile(MultipartFile file) throws Exception {
+    String fileName = FileUploadUtils.extractFilename(file);
+    PutObjectArgs args = PutObjectArgs.builder()
+        .bucket(minioConfig.getBucketName())
+        .object(fileName)
+        .stream(file.getInputStream(), file.getSize(), -1)
+        .contentType(file.getContentType())
+        .build();
+    client.putObject(args);
+    return minioConfig.getUrl() + "/" + minioConfig.getBucketName() + "/" + fileName;
+  }
+}