Parcourir la source

文件上传下载

Gaokun Wang il y a 3 semaines
Parent
commit
876100624b
16 fichiers modifiés avec 750 ajouts et 8 suppressions
  1. 37 0
      eco-common/com-core/src/main/java/org/eco/vip/core/constant/ConfigConstants.java
  2. 2 2
      eco-common/com-core/src/main/java/org/eco/vip/core/constant/Constants.java
  3. 18 0
      eco-common/com-core/src/main/java/org/eco/vip/core/utils/BooleanUtils.java
  4. 56 0
      eco-common/com-core/src/main/java/org/eco/vip/core/utils/FileDownloadUtils.java
  5. 143 0
      eco-common/com-core/src/main/java/org/eco/vip/core/utils/FileLocalUtils.java
  6. 18 0
      eco-common/com-core/src/main/java/org/eco/vip/core/utils/ImgUtils.java
  7. 18 0
      eco-common/com-core/src/main/java/org/eco/vip/core/utils/IoUtils.java
  8. 18 0
      eco-common/com-core/src/main/java/org/eco/vip/core/utils/SystemUtils.java
  9. 18 0
      eco-common/com-core/src/main/java/org/eco/vip/core/utils/URLUtils.java
  10. 56 0
      eco-nexus-core/nexus-core-biz/src/main/java/org/eco/vip/nexus/core/controller/file/FileController.java
  11. 15 4
      eco-nexus-core/nexus-core-biz/src/main/java/org/eco/vip/nexus/core/controller/user/UserController.java
  12. 30 0
      eco-nexus-core/nexus-core-biz/src/main/java/org/eco/vip/nexus/core/enums/FileEngineTypeEnum.java
  13. 21 0
      eco-nexus-core/nexus-core-biz/src/main/java/org/eco/vip/nexus/core/mapper/FileMapper.java
  14. 186 0
      eco-nexus-core/nexus-core-biz/src/main/java/org/eco/vip/nexus/core/service/file/FileService.java
  15. 112 0
      eco-nexus-core/nexus-core-biz/src/main/java/org/eco/vip/nexus/core/service/file/IFileService.java
  16. 2 2
      eco-nexus-core/nexus-core-biz/src/main/java/org/eco/vip/nexus/core/service/user/UserService.java

+ 37 - 0
eco-common/com-core/src/main/java/org/eco/vip/core/constant/ConfigConstants.java

@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2025 GaoKunW
+ *
+ */
+
+package org.eco.vip.core.constant;
+
+
+/**
+ * @description ConfigConstants
+ *
+ * @author GaoKunW
+ * @date 2025/7/22 16:35
+ */
+public class ConfigConstants {
+
+    /**
+     * 用户默认角色
+     */
+    public final static String INIT_PASSWORD_KEY = "user.init.password";
+
+    /**
+     * 默认文件引擎
+     */
+    public static final String FILE_ENGINE_KE = "default.file.engine";
+
+    /**
+     * 本地文件路径 windows
+     */
+    public static final String LOCAL_FILE_PATH_WINDOWS_KEY = "local.file.path.windows";
+
+    /**
+     * 本地文件路径 unix
+     */
+    public static final String LOCAL_FILE_PATH_UNIX_KEY = "local.file.path.unix";
+
+}

+ 2 - 2
eco-common/com-core/src/main/java/org/eco/vip/core/constant/Constants.java

@@ -50,7 +50,7 @@ public class Constants {
     public final static String SUPER_ADMIN_ROLE_KEY = "superAminRole";
 
     /**
-     * 用户默认角色
+     * 本地文件路径 unix
      */
-    public final static String INIT_PASSWORD = "user.init.password";
+    public static final String LOCAL_FILE_PATH_KEY = "localFilePath";
 }

+ 18 - 0
eco-common/com-core/src/main/java/org/eco/vip/core/utils/BooleanUtils.java

@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2025 GaoKunW
+ *
+ */
+
+package org.eco.vip.core.utils;
+
+
+import cn.hutool.core.util.BooleanUtil;
+
+/**
+ * @description BooleanUtils
+ *
+ * @author GaoKunW
+ * @date 2025/7/22 18:23
+ */
+public class BooleanUtils extends BooleanUtil {
+}

+ 56 - 0
eco-common/com-core/src/main/java/org/eco/vip/core/utils/FileDownloadUtils.java

@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2025 GaoKunW
+ *
+ */
+
+package org.eco.vip.core.utils;
+
+
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.io.IoUtil;
+import cn.hutool.core.util.URLUtil;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.extern.slf4j.Slf4j;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * @description FileDownloadUtils
+ *
+ * @author GaoKunW
+ * @date 2025/7/22 18:24
+ */
+@Slf4j
+public class FileDownloadUtils {
+
+    /**
+     * 下载文件
+     *
+     * @param file 文件
+     * @param response HttpServletResponse
+     */
+    public static void download(File file, HttpServletResponse response) {
+        download(file.getName(), FileUtil.readBytes(file), response);
+    }
+
+    /**
+     * 下载文件
+     *
+     * @param fileName 文件名
+     * @param fileBytes 文件字节数组
+     * @param response HttpServletResponse
+     */
+    public static void download(String fileName, byte[] fileBytes, HttpServletResponse response) {
+        try {
+            response.setHeader("Content-Disposition", "attachment;filename=" + URLUtil.encode(fileName));
+            response.addHeader("Content-Length", "" + fileBytes.length);
+            response.setHeader("Access-Control-Allow-Origin", "*");
+            response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
+            response.setContentType("application/octet-stream;charset=UTF-8");
+            IoUtil.write(response.getOutputStream(), true, fileBytes);
+        } catch (IOException e) {
+            log.error(">>> 文件下载异常:", e);
+        }
+    }
+}

+ 143 - 0
eco-common/com-core/src/main/java/org/eco/vip/core/utils/FileLocalUtils.java

@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2025 GaoKunW
+ *
+ */
+
+package org.eco.vip.core.utils;
+
+
+import cn.hutool.json.JSONObject;
+import cn.hutool.json.JSONUtil;
+import lombok.Getter;
+import org.eco.vip.core.api.IConfig;
+import org.eco.vip.core.constant.ConfigConstants;
+import org.eco.vip.core.constant.Constants;
+import org.eco.vip.core.exception.BusinessException;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+
+/**
+ * @description FileLocalUtils
+ *
+ * @author GaoKunW
+ * @date 2025/7/22 16:23
+ */
+public class FileLocalUtils {
+
+
+    /**
+     *  本地文件客户端
+     */
+    @Getter
+    private static JSONObject client;
+
+    /**
+     * 初始化本地文件客户端
+     */
+    private static void initClient() {
+        String uploadPath;
+        IConfig config = SpringUtils.getBean(IConfig.class);
+        if (SystemUtils.getOsInfo().isWindows()) {
+            String windowsPath = config.getConfValue(ConfigConstants.LOCAL_FILE_PATH_WINDOWS_KEY);
+            if (StrUtils.isBlank(windowsPath)) {
+                throw new BusinessException("本地文件路径 windows未配置: local.file.path.windows");
+            }
+            uploadPath = windowsPath;
+        } else {
+            String unixPath = config.getConfValue(ConfigConstants.LOCAL_FILE_PATH_UNIX_KEY);
+            if (StrUtils.isBlank(unixPath)) {
+                throw new BusinessException("本地文件路径 unix未配置: local.file.path.unix");
+            }
+            uploadPath = unixPath;
+        }
+        if (!FileUtils.exist(uploadPath)) {
+            FileUtils.mkdir(uploadPath);
+        }
+        client = JSONUtil.createObj();
+        client.set(Constants.LOCAL_FILE_PATH_KEY, uploadPath);
+    }
+
+    /**
+     * 存储文件,不返回地址
+     *
+     * @param bucketName  桶名称
+     * @param key         文件唯一名
+     * @param inputStream 文件流
+     */
+    public static void storageFile(String bucketName, String key, InputStream inputStream) {
+        initClient();
+        FileUtils.writeFromStream(inputStream, getUploadFilePath() + FileUtils.FILE_SEPARATOR + bucketName + FileUtils.FILE_SEPARATOR + key);
+    }
+
+    /**
+     * 获取上传地址
+     *
+     * @author xuyuxiang
+     * @date 2022/1/5 23:24
+     */
+    public static String getUploadFilePath() {
+        return client.getStr(Constants.LOCAL_FILE_PATH_KEY);
+    }
+
+    /**
+     * 存储文件,不返回地址
+     *
+     * @param bucketName 桶名称
+     * @param key        文件唯一名
+     * @param multipartFile      文件
+     */
+    public static void storageFile(String bucketName, String key, MultipartFile multipartFile) {
+        InputStream inputStream;
+        try {
+            inputStream = multipartFile.getInputStream();
+        } catch (IOException e) {
+            throw new BusinessException("获取文件流异常:{}", multipartFile.getName());
+        }
+        storageFile(bucketName, key, inputStream);
+    }
+
+    /**
+     * 存储文件,返回存储的地址
+     *
+     * @param bucketName 桶名称
+     * @param key         文件唯一名
+     * @param multipartFile      文件
+     */
+    public static String storageFileWithReturnUrl(String bucketName, String key, MultipartFile multipartFile) {
+        storageFile(bucketName, key, multipartFile);
+        return getFileAuthUrl(bucketName, key);
+    }
+
+    /**
+     * 获取文件的实际存储地址
+     *
+     * @param bucketName 文件桶
+     * @param key         文件唯一名
+     */
+    public static String getFileAuthUrl(String bucketName, String key) {
+        initClient();
+        File file = getFileByBucketNameAndKey(bucketName, key);
+        return file.getAbsolutePath();
+    }
+
+    /**
+     * 根据桶名称和文件key获取文件
+     *
+     * @param bucketName 文件桶
+     * @param key        唯一标示id,例如a.txt, doc/a.txt
+     * @author xuyuxiang
+     * @date 2022/1/5 23:24
+     */
+    public static File getFileByBucketNameAndKey(String bucketName, String key) {
+        initClient();
+        String path = getUploadFilePath() + FileUtils.FILE_SEPARATOR + bucketName + FileUtils.FILE_SEPARATOR + key;
+        File file = FileUtils.file(path);
+        if (!FileUtils.exist(file)) {
+            throw new BusinessException("文件{}不存在", path);
+        }
+        return file;
+    }
+}

+ 18 - 0
eco-common/com-core/src/main/java/org/eco/vip/core/utils/ImgUtils.java

@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2025 GaoKunW
+ *
+ */
+
+package org.eco.vip.core.utils;
+
+
+import cn.hutool.core.img.ImgUtil;
+
+/**
+ * @description ImgUtils
+ *
+ * @author GaoKunW
+ * @date 2025/7/22 17:49
+ */
+public class ImgUtils extends ImgUtil {
+}

+ 18 - 0
eco-common/com-core/src/main/java/org/eco/vip/core/utils/IoUtils.java

@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2025 GaoKunW
+ *
+ */
+
+package org.eco.vip.core.utils;
+
+
+import cn.hutool.core.io.IoUtil;
+
+/**
+ * @description IoUtils
+ *
+ * @author GaoKunW
+ * @date 2025/7/22 18:35
+ */
+public class IoUtils extends IoUtil {
+}

+ 18 - 0
eco-common/com-core/src/main/java/org/eco/vip/core/utils/SystemUtils.java

@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2025 GaoKunW
+ *
+ */
+
+package org.eco.vip.core.utils;
+
+
+import cn.hutool.system.SystemUtil;
+
+/**
+ * @description SystemUtils
+ *
+ * @author GaoKunW
+ * @date 2025/7/22 16:29
+ */
+public class SystemUtils extends SystemUtil {
+}

+ 18 - 0
eco-common/com-core/src/main/java/org/eco/vip/core/utils/URLUtils.java

@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2025 GaoKunW
+ *
+ */
+
+package org.eco.vip.core.utils;
+
+
+import cn.hutool.core.util.URLUtil;
+
+/**
+ * @description URLUtils
+ *
+ * @author GaoKunW
+ * @date 2025/7/22 18:26
+ */
+public class URLUtils extends URLUtil {
+}

+ 56 - 0
eco-nexus-core/nexus-core-biz/src/main/java/org/eco/vip/nexus/core/controller/file/FileController.java

@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2025 GaoKunW
+ *
+ */
+
+package org.eco.vip.nexus.core.controller.file;
+
+
+import jakarta.annotation.Resource;
+import jakarta.servlet.http.HttpServletResponse;
+import jakarta.validation.Valid;
+import org.eco.vip.core.constant.ConfigConstants;
+import org.eco.vip.core.pojo.CommonResult;
+import org.eco.vip.nexus.core.domain.file.pojo.FileBO;
+import org.eco.vip.nexus.core.service.config.IConfigService;
+import org.eco.vip.nexus.core.service.file.IFileService;
+import org.springframework.http.MediaType;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestPart;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+
+import static org.eco.vip.core.pojo.CommonResult.success;
+
+/**
+ * @description FileController
+ *
+ * @author GaoKunW
+ * @date 2025/7/22 11:07
+ */
+@RestController
+@RequestMapping("/system/file")
+@Validated
+public class FileController {
+
+    @Resource
+    private IConfigService configService;
+
+    @Resource
+    private IFileService fileService;
+
+    @PostMapping("/upload")
+    public CommonResult<String> upload(@RequestPart("file") MultipartFile file) {
+        return success(fileService.upload(configService.getConfValue(ConfigConstants.FILE_ENGINE_KE), file));
+    }
+
+    @PostMapping(value = "/download", produces = MediaType.APPLICATION_OCTET_STREAM_VALUE)
+    public CommonResult<Valid> download(@Valid FileBO fileBO, HttpServletResponse response) throws IOException {
+        fileService.download(fileBO.getFileId(), response);
+        return success();
+    }
+}

+ 15 - 4
eco-nexus-core/nexus-core-biz/src/main/java/org/eco/vip/nexus/core/controller/user/UserController.java

@@ -12,7 +12,7 @@ import jakarta.annotation.Resource;
 import jakarta.validation.Valid;
 import jakarta.validation.constraints.NotBlank;
 import jakarta.validation.constraints.NotEmpty;
-import org.eco.vip.core.constant.Constants;
+import org.eco.vip.core.constant.ConfigConstants;
 import org.eco.vip.core.pojo.CommonResult;
 import org.eco.vip.core.pojo.LoginUserStorage;
 import org.eco.vip.core.pojo.PageResult;
@@ -20,12 +20,23 @@ import org.eco.vip.core.utils.ConfigUtils;
 import org.eco.vip.core.utils.ObjUtils;
 import org.eco.vip.core.utils.StrUtils;
 import org.eco.vip.nexus.core.domain.auth.pojo.LoginUserVO;
-import org.eco.vip.nexus.core.domain.user.pojo.*;
+import org.eco.vip.nexus.core.domain.user.pojo.ModifyPasswordBO;
+import org.eco.vip.nexus.core.domain.user.pojo.UserBO;
+import org.eco.vip.nexus.core.domain.user.pojo.UserRoleBO;
+import org.eco.vip.nexus.core.domain.user.pojo.UserRoleVO;
+import org.eco.vip.nexus.core.domain.user.pojo.UserVO;
 import org.eco.vip.nexus.core.service.user.IUserService;
 import org.eco.vip.security.annotation.PermissionsResource;
 import org.eco.vip.security.utils.LoginHelper;
 import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.*;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+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.RestController;
 
 import java.util.List;
 
@@ -86,7 +97,7 @@ public class UserController {
         if (StrUtils.isBlank(userBO.getUserId())) {
             return fail("用户id不能为空!");
         }
-        userBO.setPassword(BCrypt.hashpw(ConfigUtils.getConfValue(Constants.INIT_PASSWORD)));
+        userBO.setPassword(BCrypt.hashpw(ConfigUtils.getConfValue(ConfigConstants.INIT_PASSWORD_KEY)));
         boolean result = userService.update(userBO);
         if (!result) {
             return fail("重置密码失败!");

+ 30 - 0
eco-nexus-core/nexus-core-biz/src/main/java/org/eco/vip/nexus/core/enums/FileEngineTypeEnum.java

@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2025 GaoKunW
+ *
+ */
+
+package org.eco.vip.nexus.core.enums;
+
+
+import lombok.Getter;
+
+/**
+ * @description FileEngineTypeEnum
+ *
+ * @author GaoKunW
+ * @date 2025/7/22 11:04
+ */
+@Getter
+public enum FileEngineTypeEnum {
+
+    /** 本地 */
+    LOCAL("LOCAL"),
+    /** MINIO */
+    MINIO("MINIO");
+
+    private final String value;
+
+    FileEngineTypeEnum(String value) {
+        this.value = value;
+    }
+}

+ 21 - 0
eco-nexus-core/nexus-core-biz/src/main/java/org/eco/vip/nexus/core/mapper/FileMapper.java

@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2025 GaoKunW
+ *
+ */
+
+package org.eco.vip.nexus.core.mapper;
+
+
+import com.mybatisflex.core.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+import org.eco.vip.nexus.core.domain.file.File;
+
+/**
+ * @description FileMapper
+ *
+ * @author GaoKunW
+ * @date 2025/7/22 11:09
+ */
+@Mapper
+public interface FileMapper extends BaseMapper<File> {
+}

+ 186 - 0
eco-nexus-core/nexus-core-biz/src/main/java/org/eco/vip/nexus/core/service/file/FileService.java

@@ -0,0 +1,186 @@
+/*
+ * Copyright (c) 2025 GaoKunW
+ *
+ */
+
+package org.eco.vip.nexus.core.service.file;
+
+
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.util.ObjectUtil;
+import cn.hutool.core.util.StrUtil;
+import com.mybatisflex.core.paginate.Page;
+import com.mybatisflex.core.query.QueryWrapper;
+import jakarta.annotation.Resource;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.extern.slf4j.Slf4j;
+import org.eco.vip.core.pojo.PageResult;
+import org.eco.vip.core.utils.FileDownloadUtils;
+import org.eco.vip.core.utils.FileLocalUtils;
+import org.eco.vip.core.utils.FileUtils;
+import org.eco.vip.core.utils.ImgUtils;
+import org.eco.vip.core.utils.IoUtils;
+import org.eco.vip.core.utils.MapstructUtils;
+import org.eco.vip.core.utils.StrUtils;
+import org.eco.vip.nexus.core.domain.file.File;
+import org.eco.vip.nexus.core.domain.file.pojo.FileBO;
+import org.eco.vip.nexus.core.domain.file.pojo.FileVO;
+import org.eco.vip.nexus.core.mapper.FileMapper;
+import org.eco.vip.orm.domain.PageQuery;
+import org.eco.vip.orm.service.BaseService;
+import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.UUID;
+
+import static org.eco.vip.nexus.core.domain.file.table.FileTableDef.FILE;
+
+/**
+ * @description FileService
+ *
+ * @author GaoKunW
+ * @date 2025/7/22 11:10
+ */
+@Service
+@Slf4j
+public class FileService extends BaseService<FileMapper, File> implements IFileService {
+
+    @Resource
+    private FileMapper fileMapper;
+
+    private QueryWrapper buildQueryWrapper(FileBO fileBO) {
+        return super.buildBaseQueryWrapper()
+                .and(FILE.FILE_ID.eq(fileBO.getFileId()))
+                .and(FILE.ENGINE.eq(fileBO.getEngine()))
+                .and(FILE.BUCKET.eq(fileBO.getBucket()))
+                .and(FILE.FILE_NAME.eq(fileBO.getFileName()))
+                .and(FILE.ORIGINAL_NAME.eq(fileBO.getOriginalName()))
+                .and(FILE.STATUS.eq(fileBO.getStatus()));
+    }
+
+    @Override
+    public PageResult<FileVO> selectPage(FileBO fileBO) {
+        QueryWrapper queryWrapper = buildQueryWrapper(fileBO);
+        Page<FileVO> page = fileMapper.paginateWithRelationsAs(PageQuery.build(), queryWrapper, FileVO.class);
+        return PageResult.build(page);
+    }
+
+    @Override
+    public List<FileVO> selectList(FileBO fileBO) {
+        QueryWrapper queryWrapper = buildQueryWrapper(fileBO);
+        return fileMapper.selectListWithRelationsByQueryAs(queryWrapper, FileVO.class);
+    }
+
+    @Override
+    public boolean insert(FileBO fileBO) {
+        File file = MapstructUtils.convert(fileBO, File.class);
+        return this.save(file);
+    }
+
+    @Override
+    public boolean update(FileBO fileBO) {
+        File file = MapstructUtils.convert(fileBO, File.class);
+        return this.updateById(file);
+    }
+
+    @Override
+    public boolean delete(List<String> ids) {
+        return this.removeByIds(ids);
+    }
+
+    @Override
+    public boolean deleteFile(List<String> ids) {
+        return false;
+    }
+
+    @Override
+    public FileVO selectById(String id) {
+        QueryWrapper queryWrapper = query().where(FILE.FILE_ID.eq(id).when(StrUtils.isNotBlank(id))).and(FILE.FILE_ID.isNull().when(StrUtils.isBlank(id)));
+        return this.getOneAs(queryWrapper, FileVO.class);
+    }
+
+    @Override
+    public List<FileVO> selectByUrl(List<String> urls) {
+        QueryWrapper queryWrapper = query().where(FILE.DOWNLOAD_URL.in(urls));
+        return fileMapper.selectListWithRelationsByQueryAs(queryWrapper, FileVO.class);
+    }
+
+    @Override
+    public String upload(String engine, MultipartFile file) {
+        return this.storageFile(engine, file);
+    }
+
+    @Override
+    public void download(String id, HttpServletResponse response) throws IOException {
+
+    }
+
+    @Override
+    public void authDownload(String id, HttpServletResponse response) throws IOException {
+
+    }
+
+    /**
+     * 存储文件
+     *
+     * @param engine         引擎
+     * @param file           文件
+     * @return 文件id/url
+     */
+    private String storageFile(String engine, MultipartFile file) {
+        String key = UUID.randomUUID().toString().replace("-", "");
+        String storageUrl = FileLocalUtils.storageFileWithReturnUrl("LocalBucket", key, file);
+        File fileInfo = new File();
+        fileInfo.setFileId(key);
+        fileInfo.setEngine(engine);
+        fileInfo.setBucket("LocalBucket");
+        fileInfo.setOriginalName(file.getOriginalFilename());
+        fileInfo.setDownloadUrl(storageUrl);
+        String suffix = ObjectUtil.isNotEmpty(file.getOriginalFilename()) ? StrUtil.subAfter(file.getOriginalFilename(),
+                StrUtil.DOT, true) : null;
+        fileInfo.setFileSuffix(suffix);
+        fileInfo.setSizeKb(12);
+        fileInfo.setSizeInfo(FileUtils.readableFileSize(file.getSize()));
+        fileInfo.setFileName(ObjectUtil.isNotEmpty(fileInfo.getFileSuffix()) ? key + StrUtil.DOT + fileInfo.getFileSuffix() : null);
+        if (ObjectUtil.isNotEmpty(suffix)) {
+            if (isPic(suffix)) {
+                try {
+                    fileInfo.setThumbnail(ImgUtils.toBase64DataUri(ImgUtils.scale(ImgUtils.toImage(file.getBytes()),
+                            100, 100, null), suffix));
+                } catch (Exception ignored) {
+                }
+            }
+        }
+        fileInfo.setStorageUrl(storageUrl);
+
+        this.save(fileInfo);
+        return "";
+    }
+
+    private void unifiedDownload(FileBO fileBO, HttpServletResponse response, boolean isDownloadAuth) {
+        FileVO fileVO = this.selectById(fileBO.getFileId());
+        java.io.File file = FileUtils.file(fileVO.getStorageUrl());
+        if (!FileUtil.exist(file)) {
+            return;
+        }
+        FileDownloadUtils.download(file.getName(), IoUtils.readBytes(FileUtil.getInputStream(file)), response);
+    }
+
+    /**
+     * 判断是否是图片
+     *
+     * @param fileSuffix 文件后缀
+     * @return 是否是图片
+     */
+    private static boolean isPic(String fileSuffix) {
+        fileSuffix = fileSuffix.toLowerCase();
+        return ImgUtils.IMAGE_TYPE_GIF.equals(fileSuffix)
+                || ImgUtils.IMAGE_TYPE_JPG.equals(fileSuffix)
+                || ImgUtils.IMAGE_TYPE_JPEG.equals(fileSuffix)
+                || ImgUtils.IMAGE_TYPE_BMP.equals(fileSuffix)
+                || ImgUtils.IMAGE_TYPE_PNG.equals(fileSuffix)
+                || ImgUtils.IMAGE_TYPE_PSD.equals(fileSuffix);
+    }
+}

+ 112 - 0
eco-nexus-core/nexus-core-biz/src/main/java/org/eco/vip/nexus/core/service/file/IFileService.java

@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2025 GaoKunW
+ *
+ */
+
+package org.eco.vip.nexus.core.service.file;
+
+
+import jakarta.servlet.http.HttpServletResponse;
+import org.eco.vip.core.pojo.PageResult;
+import org.eco.vip.nexus.core.domain.file.File;
+import org.eco.vip.nexus.core.domain.file.pojo.FileBO;
+import org.eco.vip.nexus.core.domain.file.pojo.FileVO;
+import org.eco.vip.orm.service.IBaseService;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * @description IFileService
+ *
+ * @author GaoKunW
+ * @date 2025/7/22 11:10
+ */
+public interface IFileService extends IBaseService<File> {
+
+    /**
+     * @description: 分页查询
+     * @param fileBO 参数
+     * @return PageResult<OrgVO>
+     **/
+    PageResult<FileVO> selectPage(FileBO fileBO);
+
+    /**
+     * @description: 查询
+     * @param fileBO 参数
+     * @return List<FileVO>
+     **/
+    List<FileVO> selectList(FileBO fileBO);
+
+    /**
+     * @description: 新增
+     * @param fileBO 参数
+     * @return boolean 是否成功
+     **/
+    boolean insert(FileBO fileBO);
+
+    /**
+     * @description: 更新
+     * @param fileBO 参数
+     * @return boolean 是否成功
+     **/
+    boolean update(FileBO fileBO);
+
+    /**
+     * @description: 删除
+     * @param ids ids
+     * @return boolean 是否成功
+     **/
+    boolean delete(List<String> ids);
+
+    /**
+     * @description: 删除存储空间文件
+     * @param ids ids
+     * @return boolean 是否成功
+     **/
+    boolean deleteFile(List<String> ids);
+
+    /**
+     * 根据ID查询信息
+     *
+     * @param id ID
+     * @return 信息
+     */
+    FileVO selectById(String id);
+
+    /**
+     * 根据url查询信息
+     *
+     * @param urls urls
+     * @return 信息
+     */
+    List<FileVO> selectByUrl(List<String> urls);
+
+    /**
+     * MultipartFile文件上传,返回文件id
+     *
+     * @param engine 引擎名
+     * @param file 文件
+     * @return id
+     */
+    String upload(String engine, MultipartFile file);
+
+    /**
+     * 文件下载
+     *
+     * @param id 文件id
+     * @param response 响应
+     * @throws IOException IO异常
+     */
+    void download(String id, HttpServletResponse response) throws IOException;
+
+    /**
+     * 文件授权下载
+     *
+     * @param id 文件id
+     * @param response 响应
+     * @throws IOException IO异常
+     */
+    void authDownload(String id, HttpServletResponse response) throws IOException;
+}

+ 2 - 2
eco-nexus-core/nexus-core-biz/src/main/java/org/eco/vip/nexus/core/service/user/UserService.java

@@ -12,7 +12,7 @@ import com.mybatisflex.core.query.QueryMethods;
 import com.mybatisflex.core.query.QueryWrapper;
 import com.mybatisflex.core.update.UpdateChain;
 import jakarta.annotation.Resource;
-import org.eco.vip.core.constant.Constants;
+import org.eco.vip.core.constant.ConfigConstants;
 import org.eco.vip.core.pojo.PageResult;
 import org.eco.vip.core.utils.ConfigUtils;
 import org.eco.vip.core.utils.MapstructUtils;
@@ -78,7 +78,7 @@ public class UserService extends BaseService<UserMapper, User> implements IUserS
 
     @Override
     public boolean insert(UserBO userBO) {
-        userBO.setPassword(BCrypt.hashpw(ConfigUtils.getConfValue(Constants.INIT_PASSWORD)));
+        userBO.setPassword(BCrypt.hashpw(ConfigUtils.getConfValue(ConfigConstants.INIT_PASSWORD_KEY)));
         User user = MapstructUtils.convert(userBO, User.class);
         return this.save(user);
     }