From c86bfa92432bde3c1e3ea6891cf5c43c2e99cd3d Mon Sep 17 00:00:00 2001
From: RuoYi <yzz_ivy@163.com>
Date: Fri, 06 Jun 2025 19:36:36 +0800
Subject: [PATCH] 用户头像更换后移除旧头像文件

---
 ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/factory/RemoteFileFallbackFactory.java |    6 ++
 ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/LocalSysFileServiceImpl.java           |   15 +++++
 ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/MinioSysFileServiceImpl.java           |   22 +++++++
 ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/file/FileUtils.java         |   10 +-
 ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/controller/SysFileController.java              |   26 ++++++++
 ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml                        |   18 +++---
 ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/FastDfsSysFileServiceImpl.java         |   22 +++++++
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysProfileController.java       |   11 ++-
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java                  |    8 +-
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java               |    8 +-
 ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/RemoteFileService.java                 |   11 +++
 ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/ISysFileService.java                   |    8 ++
 ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java       |   12 ++--
 13 files changed, 144 insertions(+), 33 deletions(-)

diff --git a/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/RemoteFileService.java b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/RemoteFileService.java
index ae56a54..688bb46 100644
--- a/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/RemoteFileService.java
+++ b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/RemoteFileService.java
@@ -2,7 +2,9 @@
 
 import org.springframework.cloud.openfeign.FeignClient;
 import org.springframework.http.MediaType;
+import org.springframework.web.bind.annotation.DeleteMapping;
 import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RequestPart;
 import org.springframework.web.multipart.MultipartFile;
 import com.ruoyi.common.core.constant.ServiceNameConstants;
@@ -26,4 +28,13 @@
      */
     @PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
     public R<SysFile> upload(@RequestPart(value = "file") MultipartFile file);
+
+    /**
+     * 删除文件
+     *
+     * @param fileUrl 文件地址
+     * @return 结果
+     */
+    @DeleteMapping(value = "/delete", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
+    public R<Boolean> delete(@RequestParam("fileUrl") String fileUrl);
 }
diff --git a/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/factory/RemoteFileFallbackFactory.java b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/factory/RemoteFileFallbackFactory.java
index bc3b6ff..421eb94 100644
--- a/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/factory/RemoteFileFallbackFactory.java
+++ b/ruoyi-api/ruoyi-api-system/src/main/java/com/ruoyi/system/api/factory/RemoteFileFallbackFactory.java
@@ -30,6 +30,12 @@
             {
                 return R.fail("上传文件失败:" + throwable.getMessage());
             }
+
+            @Override
+            public R<Boolean> delete(String fileUrl)
+            {
+                return R.fail("删除文件失败:" + throwable.getMessage());
+            }
         };
     }
 }
diff --git a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/file/FileUtils.java b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/file/FileUtils.java
index 0c28db7..aabb4fb 100644
--- a/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/file/FileUtils.java
+++ b/ruoyi-common/ruoyi-common-core/src/main/java/com/ruoyi/common/core/utils/file/FileUtils.java
@@ -114,20 +114,20 @@
     }
 
     /**
-     * 检查文件是否可下载
+     * 校验文件路径合法性(安全性与扩展名)
      * 
-     * @param resource 需要下载的文件
+     * @param fileUrl 待校验的文件地址
      * @return true 正常 false 非法
      */
-    public static boolean checkAllowDownload(String resource)
+    public static boolean validateFilePath(String fileUrl)
     {
         // 禁止目录上跳级别
-        if (StringUtils.contains(resource, ".."))
+        if (StringUtils.contains(fileUrl, ".."))
         {
             return false;
         }
         // 判断是否在允许下载的文件规则内
-        return ArrayUtils.contains(MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, FileTypeUtils.getFileType(resource));
+        return ArrayUtils.contains(MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, FileTypeUtils.getFileType(fileUrl));
     }
 
     /**
diff --git a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/controller/SysFileController.java b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/controller/SysFileController.java
index 318db41..82db19b 100644
--- a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/controller/SysFileController.java
+++ b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/controller/SysFileController.java
@@ -3,10 +3,12 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.DeleteMapping;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RestController;
 import org.springframework.web.multipart.MultipartFile;
 import com.ruoyi.common.core.domain.R;
+import com.ruoyi.common.core.utils.StringUtils;
 import com.ruoyi.common.core.utils.file.FileUtils;
 import com.ruoyi.file.service.ISysFileService;
 import com.ruoyi.system.api.domain.SysFile;
@@ -45,4 +47,26 @@
             return R.fail(e.getMessage());
         }
     }
-}
\ No newline at end of file
+
+    /**
+     * 文件删除请求
+     */
+    @DeleteMapping("delete")
+    public R<Boolean> delete(String fileUrl)
+    {
+        try
+        {
+            if (!FileUtils.validateFilePath(fileUrl))
+            {
+                throw new Exception(StringUtils.format("资源文件({})非法,不允许删除。 ", fileUrl));
+            }
+            sysFileService.deleteFile(fileUrl);
+            return R.ok();
+        }
+        catch (Exception e)
+        {
+            log.error("删除文件失败", e);
+            return R.fail(e.getMessage());
+        }
+    }
+}
diff --git a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/FastDfsSysFileServiceImpl.java b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/FastDfsSysFileServiceImpl.java
index da0dc60..456c697 100644
--- a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/FastDfsSysFileServiceImpl.java
+++ b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/FastDfsSysFileServiceImpl.java
@@ -1,11 +1,11 @@
 package com.ruoyi.file.service;
 
 import java.io.InputStream;
-import com.alibaba.nacos.common.utils.IoUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 import org.springframework.web.multipart.MultipartFile;
+import com.alibaba.nacos.common.utils.IoUtils;
 import com.github.tobato.fastdfs.domain.fdfs.StorePath;
 import com.github.tobato.fastdfs.service.FastFileStorageClient;
 import com.ruoyi.common.core.utils.file.FileTypeUtils;
@@ -53,4 +53,24 @@
             IoUtils.closeQuietly(inputStream);
         }
     }
+
+    /**
+     * FastDFS文件删除接口
+     * 
+     * @param fileUrl 文件访问URL
+     * @throws Exception
+     */
+    @Override
+    public void deleteFile(String fileUrl) throws Exception
+    {
+        try
+        {
+            StorePath storePath = StorePath.parseFromUrl(fileUrl);
+            storageClient.deleteFile(storePath.getGroup(), storePath.getPath());
+        }
+        catch (Exception e)
+        {
+            throw new RuntimeException("FastDfs Failed to delete file: ", e);
+        }
+    }
 }
diff --git a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/ISysFileService.java b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/ISysFileService.java
index 5a35348..d6119ef 100644
--- a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/ISysFileService.java
+++ b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/ISysFileService.java
@@ -17,4 +17,12 @@
      * @throws Exception
      */
     public String uploadFile(MultipartFile file) throws Exception;
+
+    /**
+     * 文件删除接口
+     * 
+     * @param fileUrl 文件访问URL
+     * @throws Exception
+     */
+    public void deleteFile(String fileUrl) throws Exception;
 }
diff --git a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/LocalSysFileServiceImpl.java b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/LocalSysFileServiceImpl.java
index c0e2068..56c6afd 100644
--- a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/LocalSysFileServiceImpl.java
+++ b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/LocalSysFileServiceImpl.java
@@ -4,6 +4,8 @@
 import org.springframework.context.annotation.Primary;
 import org.springframework.stereotype.Service;
 import org.springframework.web.multipart.MultipartFile;
+import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.core.utils.file.FileUtils;
 import com.ruoyi.file.utils.FileUploadUtils;
 
 /**
@@ -47,4 +49,17 @@
         String url = domain + localFilePrefix + name;
         return url;
     }
+
+    /**
+     * 本地文件删除接口
+     * 
+     * @param fileUrl 文件访问URL
+     * @throws Exception
+     */
+    @Override
+    public void deleteFile(String fileUrl) throws Exception
+    {
+        String localFile = StringUtils.substringAfter(fileUrl, localFilePrefix);
+        FileUtils.deleteFile(localFilePath + localFile);
+    }
 }
diff --git a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/MinioSysFileServiceImpl.java b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/MinioSysFileServiceImpl.java
index eade4c8..9afd291 100644
--- a/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/MinioSysFileServiceImpl.java
+++ b/ruoyi-modules/ruoyi-file/src/main/java/com/ruoyi/file/service/MinioSysFileServiceImpl.java
@@ -5,10 +5,12 @@
 import org.springframework.stereotype.Service;
 import org.springframework.web.multipart.MultipartFile;
 import com.alibaba.nacos.common.utils.IoUtils;
+import com.ruoyi.common.core.utils.StringUtils;
 import com.ruoyi.file.config.MinioConfig;
 import com.ruoyi.file.utils.FileUploadUtils;
 import io.minio.MinioClient;
 import io.minio.PutObjectArgs;
+import io.minio.RemoveObjectArgs;
 
 /**
  * Minio 文件存储
@@ -57,4 +59,24 @@
             IoUtils.closeQuietly(inputStream);
         }
     }
+
+    /**
+     * Minio文件删除接口
+     * 
+     * @param fileUrl 文件访问URL
+     * @throws Exception
+     */
+    @Override
+    public void deleteFile(String fileUrl) throws Exception
+    {
+        try
+        {
+            String minioFile = StringUtils.substringAfter(fileUrl, minioConfig.getBucketName());
+            client.removeObject(RemoveObjectArgs.builder().bucket(minioConfig.getBucketName()).object(minioFile).build());
+        }
+        catch (Exception e)
+        {
+            throw new RuntimeException("Minio Failed to delete file", e);
+        }
+    }
 }
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysProfileController.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysProfileController.java
index 9c5d148..83aab06 100644
--- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysProfileController.java
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/controller/SysProfileController.java
@@ -100,7 +100,7 @@
         String oldPassword = params.get("oldPassword");
         String newPassword = params.get("newPassword");
         LoginUser loginUser = SecurityUtils.getLoginUser();
-        String userName = loginUser.getUsername();
+        Long userId = loginUser.getUserid();
         String password = loginUser.getSysUser().getPassword();
         if (!SecurityUtils.matchesPassword(oldPassword, password))
         {
@@ -111,7 +111,7 @@
             return error("新密码不能与旧密码相同");
         }
         newPassword = SecurityUtils.encryptPassword(newPassword);
-        if (userService.resetUserPwd(userName, newPassword) > 0)
+        if (userService.resetUserPwd(userId, newPassword) > 0)
         {
             // 更新缓存用户密码&密码最后更新时间
             loginUser.getSysUser().setPwdUpdateDate(DateUtils.getNowDate());
@@ -143,8 +143,13 @@
                 return error("文件服务异常,请联系管理员");
             }
             String url = fileResult.getData().getUrl();
-            if (userService.updateUserAvatar(loginUser.getUsername(), url))
+            if (userService.updateUserAvatar(loginUser.getUserid(), url))
             {
+                String oldAvatarUrl = loginUser.getSysUser().getAvatar();
+                if (StringUtils.isNotEmpty(oldAvatarUrl))
+                {
+                    remoteFileService.delete(oldAvatarUrl);
+                }
                 AjaxResult ajax = AjaxResult.success();
                 ajax.put("imgUrl", url);
                 // 更新缓存用户头像
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java
index 9535ab8..d9f99fa 100644
--- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysUserMapper.java
@@ -70,20 +70,20 @@
     /**
      * 修改用户头像
      * 
-     * @param userName 用户名
+     * @param userId 用户ID
      * @param avatar 头像地址
      * @return 结果
      */
-    public int updateUserAvatar(@Param("userName") String userName, @Param("avatar") String avatar);
+    public int updateUserAvatar(@Param("userId") Long userId, @Param("avatar") String avatar);
 
     /**
      * 重置用户密码
      * 
-     * @param userName 用户名
+     * @param userId 用户ID
      * @param password 密码
      * @return 结果
      */
-    public int resetUserPwd(@Param("userName") String userName, @Param("password") String password);
+    public int resetUserPwd(@Param("userId") Long userId, @Param("password") String password);
 
     /**
      * 通过用户ID删除用户
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java
index 83208dc..1ba6021 100644
--- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/ISysUserService.java
@@ -155,11 +155,11 @@
     /**
      * 修改用户头像
      * 
-     * @param userName 用户名
+     * @param userId 用户ID
      * @param avatar 头像地址
      * @return 结果
      */
-    public boolean updateUserAvatar(String userName, String avatar);
+    public boolean updateUserAvatar(Long userId, String avatar);
 
     /**
      * 重置用户密码
@@ -172,11 +172,11 @@
     /**
      * 重置用户密码
      * 
-     * @param userName 用户名
+     * @param userId 用户ID
      * @param password 密码
      * @return 结果
      */
-    public int resetUserPwd(String userName, String password);
+    public int resetUserPwd(Long userId, String password);
 
     /**
      * 通过用户ID删除用户
diff --git a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java
index 99fbb35..80487d8 100644
--- a/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java
+++ b/ruoyi-modules/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/SysUserServiceImpl.java
@@ -344,14 +344,14 @@
     /**
      * 修改用户头像
      * 
-     * @param userName 用户名
+     * @param userId 用户ID
      * @param avatar 头像地址
      * @return 结果
      */
     @Override
-    public boolean updateUserAvatar(String userName, String avatar)
+    public boolean updateUserAvatar(Long userId, String avatar)
     {
-        return userMapper.updateUserAvatar(userName, avatar) > 0;
+        return userMapper.updateUserAvatar(userId, avatar) > 0;
     }
 
     /**
@@ -369,14 +369,14 @@
     /**
      * 重置用户密码
      * 
-     * @param userName 用户名
+     * @param userId 用户ID
      * @param password 密码
      * @return 结果
      */
     @Override
-    public int resetUserPwd(String userName, String password)
+    public int resetUserPwd(Long userId, String password)
     {
-        return userMapper.resetUserPwd(userName, password);
+        return userMapper.resetUserPwd(userId, password);
     }
 
     /**
diff --git a/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml b/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml
index 823af75..02a67ff 100644
--- a/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml
+++ b/ruoyi-modules/ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml
@@ -19,13 +19,13 @@
         <result property="loginIp"       column="login_ip"        />
         <result property="loginDate"     column="login_date"      />
         <result property="pwdUpdateDate" column="pwd_update_date" />
-        <result property="createBy"     column="create_by"        />
-        <result property="createTime"   column="create_time"      />
-        <result property="updateBy"     column="update_by"        />
-        <result property="updateTime"   column="update_time"      />
-        <result property="remark"       column="remark"           />
-        <association property="dept"    javaType="SysDept"         resultMap="deptResult" />
-        <collection  property="roles"   javaType="java.util.List"  resultMap="RoleResult" />
+        <result property="createBy"      column="create_by"       />
+        <result property="createTime"    column="create_time"     />
+        <result property="updateBy"      column="update_by"       />
+        <result property="updateTime"    column="update_time"     />
+        <result property="remark"        column="remark"          />
+        <association property="dept"     javaType="SysDept"         resultMap="deptResult" />
+        <collection  property="roles"    javaType="java.util.List"  resultMap="RoleResult" />
     </resultMap>
 	
     <resultMap id="deptResult" type="SysDept">
@@ -202,11 +202,11 @@
 	</update>
 	
 	<update id="updateUserAvatar" parameterType="SysUser">
- 		update sys_user set avatar = #{avatar} where user_name = #{userName}
+ 		update sys_user set avatar = #{avatar} where user_id = #{userId}
 	</update>
 	
 	<update id="resetUserPwd" parameterType="SysUser">
- 		update sys_user set pwd_update_date = sysdate(), password = #{password} where user_name = #{userName}
+ 		update sys_user set pwd_update_date = sysdate(), password = #{password} where user_id = #{userId}
 	</update>
 	
 	<delete id="deleteUserById" parameterType="Long">

--
Gitblit v1.9.3