diff --git a/src/main/java/com/guaiguailang/harmony/constant/FileUploadFolder.java b/src/main/java/com/guaiguailang/harmony/constant/FileUploadFolder.java deleted file mode 100644 index 8db76e0..0000000 --- a/src/main/java/com/guaiguailang/harmony/constant/FileUploadFolder.java +++ /dev/null @@ -1,6 +0,0 @@ -package com.guaiguailang.harmony.constant; - -public class FileUploadFolder { - public static final String USER_AVATER_FOLDER = "userAvatar"; - public static final String ACTIVITY_FOLDER = "activity"; -} diff --git a/src/main/java/com/guaiguailang/harmony/constant/SystemConfigKey.java b/src/main/java/com/guaiguailang/harmony/constant/SystemConfigKey.java new file mode 100644 index 0000000..e6c85c0 --- /dev/null +++ b/src/main/java/com/guaiguailang/harmony/constant/SystemConfigKey.java @@ -0,0 +1,8 @@ +package com.guaiguailang.harmony.constant; + +public class SystemConfigKey { + public static final String SYS_CONFIG_URL_BACK = "back_url"; + public static final String SYS_CONFIG_URL_FRONT = "front_url"; + public static final String SYS_FILE_SAVE_PATH = "file_save"; + +} diff --git a/src/main/java/com/guaiguailang/harmony/controller/ActivateController.java b/src/main/java/com/guaiguailang/harmony/controller/ActivateController.java new file mode 100644 index 0000000..bf5f768 --- /dev/null +++ b/src/main/java/com/guaiguailang/harmony/controller/ActivateController.java @@ -0,0 +1,4 @@ +package com.guaiguailang.harmony.controller; + +public class ActivateController { +} diff --git a/src/main/java/com/guaiguailang/harmony/controller/UploadController.java b/src/main/java/com/guaiguailang/harmony/controller/UploadController.java index 66ea975..b440318 100644 --- a/src/main/java/com/guaiguailang/harmony/controller/UploadController.java +++ b/src/main/java/com/guaiguailang/harmony/controller/UploadController.java @@ -2,15 +2,17 @@ package com.guaiguailang.harmony.controller; import cn.dev33.satoken.stp.StpUtil; import com.guaiguailang.harmony.domain.vo.ResponseResult; +import com.guaiguailang.harmony.service.ActivateService; +import com.guaiguailang.harmony.service.FileService; import com.guaiguailang.harmony.service.UserService; +import com.guaiguailang.harmony.utils.FileUpload; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.core.io.Resource; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; @Tag(name="文件上传接口") @@ -21,7 +23,10 @@ public class UploadController { @Autowired private UserService userService; - + @Autowired + private ActivateService activateService; + @Autowired + private FileService fileService; /** * 修改用户头像 @@ -40,5 +45,32 @@ public class UploadController { } return ResponseResult.success(imgUrl); } - + /** + * 上传活动头图 + * @param file + * @return + */ + @Operation(summary = "活动 头图") + @PostMapping("/activate/profile") + public ResponseResult uploadActivateProfile(@RequestParam("file") MultipartFile file){ + if(file.isEmpty()){ + return ResponseResult.error("图片为空,请重新选择"); + } + String imgUrl = activateService.uploadActivateProfile(file); + if(imgUrl==null){ + return ResponseResult.error("图片上传失败"); + } + return ResponseResult.success(imgUrl); + } + // 编写Controller ,实现根据md5值获取文件 + /** + * 根据文件的 MD5 值获取文件的访问路径 + * @param fileMd5 文件的 MD5 值 + * @return 文件的访问路径 + */ + @Operation(summary = "根据文件的 MD5 值获取文件的访问路径") + @GetMapping("/{fileMd5}") + public ResponseEntity getFilePathByMd5(@PathVariable ("fileMd5") String fileMd5) { + return fileService.getFileObj(fileMd5); + } } diff --git a/src/main/java/com/guaiguailang/harmony/domain/entity/SystemConfig.java b/src/main/java/com/guaiguailang/harmony/domain/entity/SystemConfig.java new file mode 100644 index 0000000..23cf4e2 --- /dev/null +++ b/src/main/java/com/guaiguailang/harmony/domain/entity/SystemConfig.java @@ -0,0 +1,47 @@ +package com.guaiguailang.harmony.domain.entity; + + +public class SystemConfig { + + private long id; + private String key; + private String value; + private String description; + + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + + public String getKey() { + return key; + } + + public void setKey(String key) { + this.key = key; + } + + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + +} diff --git a/src/main/java/com/guaiguailang/harmony/domain/entity/SystemFile.java b/src/main/java/com/guaiguailang/harmony/domain/entity/SystemFile.java new file mode 100644 index 0000000..eb0c561 --- /dev/null +++ b/src/main/java/com/guaiguailang/harmony/domain/entity/SystemFile.java @@ -0,0 +1,18 @@ +package com.guaiguailang.harmony.domain.entity; + +import lombok.Data; + +@Data +public class SystemFile { + + private long id; + private String fileName; + private String fileType; + private double fileSize; + private String fileMd5; + private String plate; + private String description; + private String path; + private String url; + +} diff --git a/src/main/java/com/guaiguailang/harmony/mapper/ConfigMapper.java b/src/main/java/com/guaiguailang/harmony/mapper/ConfigMapper.java new file mode 100644 index 0000000..6584efb --- /dev/null +++ b/src/main/java/com/guaiguailang/harmony/mapper/ConfigMapper.java @@ -0,0 +1,13 @@ +package com.guaiguailang.harmony.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.guaiguailang.harmony.domain.entity.SystemConfig; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Select; + + +@Mapper +public interface ConfigMapper extends BaseMapper { + @Select("SELECT `value` from system_config where `key`=#{key}") + String getKeyValue(String key); +} diff --git a/src/main/java/com/guaiguailang/harmony/mapper/FileMapper.java b/src/main/java/com/guaiguailang/harmony/mapper/FileMapper.java new file mode 100644 index 0000000..8e57d8b --- /dev/null +++ b/src/main/java/com/guaiguailang/harmony/mapper/FileMapper.java @@ -0,0 +1,20 @@ +package com.guaiguailang.harmony.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.guaiguailang.harmony.domain.entity.SystemFile; +import org.apache.ibatis.annotations.Insert; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.annotations.Select; + +@Mapper +public interface FileMapper extends BaseMapper { + @Select("select * from system_file where `file_md5`=#{md5}") + SystemFile getFileByMd5(String md5); + + @Insert("INSERT INTO system_file (`id`, `file_name`, `file_type`, `file_size`, `file_md5`, `plate`, `description`, `path`, `url`) " + + "VALUES (#{id}, #{fileName}, #{ext}, #{fileSize}, #{md5}, #{plate}, #{description}, #{filePath}, #{url})") + void save(@Param("id") long id, @Param("fileName") String fileName, @Param("ext") String ext, @Param("fileSize") double fileSize, + @Param("md5") String md5, @Param("plate") String plate, @Param("description") String description, + @Param("filePath") String filePath, @Param("url") String url); +} diff --git a/src/main/java/com/guaiguailang/harmony/mapper/UserMapper.java b/src/main/java/com/guaiguailang/harmony/mapper/UserMapper.java index 3ddac85..072e047 100644 --- a/src/main/java/com/guaiguailang/harmony/mapper/UserMapper.java +++ b/src/main/java/com/guaiguailang/harmony/mapper/UserMapper.java @@ -5,10 +5,7 @@ import com.guaiguailang.harmony.domain.dto.ParamUserAdd; import com.guaiguailang.harmony.domain.entity.SystemRole; import com.guaiguailang.harmony.domain.entity.UserInfo; import com.guaiguailang.harmony.domain.vo.UserListNum; -import org.apache.ibatis.annotations.Mapper; -import org.apache.ibatis.annotations.Param; -import org.apache.ibatis.annotations.Select; -import org.apache.ibatis.annotations.Update; +import org.apache.ibatis.annotations.*; import java.util.List; import java.util.Map; @@ -44,4 +41,6 @@ public interface UserMapper extends BaseMapper { Integer changeDelete(Long id); @Update("update user_info set name=#{name},email=#{email},telephone=#{telephone} where id=#{id}") Integer selfUpdateUserInfo(Long id, String name, String email, String telephone); + @Update("UPDATE user_info set avatar=#{url} where id=#{uid}") + void updateUserAvatar(Long uid, String url); } diff --git a/src/main/java/com/guaiguailang/harmony/service/ActivateService.java b/src/main/java/com/guaiguailang/harmony/service/ActivateService.java new file mode 100644 index 0000000..7aa2c10 --- /dev/null +++ b/src/main/java/com/guaiguailang/harmony/service/ActivateService.java @@ -0,0 +1,7 @@ +package com.guaiguailang.harmony.service; + +import org.springframework.web.multipart.MultipartFile; + +public interface ActivateService { + String uploadActivateProfile(MultipartFile file); +} diff --git a/src/main/java/com/guaiguailang/harmony/service/FileService.java b/src/main/java/com/guaiguailang/harmony/service/FileService.java new file mode 100644 index 0000000..99cbf46 --- /dev/null +++ b/src/main/java/com/guaiguailang/harmony/service/FileService.java @@ -0,0 +1,8 @@ +package com.guaiguailang.harmony.service; + +import org.springframework.core.io.Resource; +import org.springframework.http.ResponseEntity; + +public interface FileService { + ResponseEntity getFileObj(String fileMd5); +} diff --git a/src/main/java/com/guaiguailang/harmony/service/impl/ActivateServiceImpl.java b/src/main/java/com/guaiguailang/harmony/service/impl/ActivateServiceImpl.java new file mode 100644 index 0000000..d3d2a46 --- /dev/null +++ b/src/main/java/com/guaiguailang/harmony/service/impl/ActivateServiceImpl.java @@ -0,0 +1,18 @@ +package com.guaiguailang.harmony.service.impl; +import com.guaiguailang.harmony.service.ActivateService; +import com.guaiguailang.harmony.utils.FileUpload; +import com.guaiguailang.harmony.utils.UtilMD5; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +@Service +public class ActivateServiceImpl implements ActivateService { + @Autowired + private FileUpload fileUpload; + + @Override + public String uploadActivateProfile(MultipartFile file) { + return fileUpload.uploadFile(file,file.getName(),"activate","活动头图"); + } +} diff --git a/src/main/java/com/guaiguailang/harmony/service/impl/AuthServiceImpl.java b/src/main/java/com/guaiguailang/harmony/service/impl/AuthServiceImpl.java index 8ac7dea..2a64a05 100644 --- a/src/main/java/com/guaiguailang/harmony/service/impl/AuthServiceImpl.java +++ b/src/main/java/com/guaiguailang/harmony/service/impl/AuthServiceImpl.java @@ -1,7 +1,6 @@ package com.guaiguailang.harmony.service.impl; import cn.dev33.satoken.stp.StpUtil; -import cn.dev33.satoken.util.SaResult; import com.github.yitter.idgen.YitIdHelper; import com.guaiguailang.harmony.domain.dto.ParamLogin; import com.guaiguailang.harmony.domain.entity.SystemRole; diff --git a/src/main/java/com/guaiguailang/harmony/service/impl/FileServiceImpl.java b/src/main/java/com/guaiguailang/harmony/service/impl/FileServiceImpl.java new file mode 100644 index 0000000..f7d86c7 --- /dev/null +++ b/src/main/java/com/guaiguailang/harmony/service/impl/FileServiceImpl.java @@ -0,0 +1,40 @@ +package com.guaiguailang.harmony.service.impl; + +import com.guaiguailang.harmony.domain.entity.SystemFile; +import com.guaiguailang.harmony.mapper.FileMapper; +import com.guaiguailang.harmony.service.FileService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.io.FileSystemResource; +import org.springframework.core.io.Resource; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Service; + +@Service +public class FileServiceImpl implements FileService { + + @Autowired + private FileMapper fileMapper; + + @Override + public ResponseEntity getFileObj(String fileMd5) { + SystemFile systemFile = fileMapper.getFileByMd5(fileMd5); + if (systemFile == null) { + return ResponseEntity.notFound().build(); + } + + String realAddress = systemFile.getPath(); // 真实的文件存储地址 + Resource resource = new FileSystemResource(realAddress); + + if (resource.exists() && resource.isReadable()) { + return ResponseEntity.ok() + .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + systemFile.getFileName() + "\"") + .contentType(MediaType.APPLICATION_OCTET_STREAM) + .body(resource); + } else { + return ResponseEntity.status(HttpStatus.NOT_FOUND).build(); + } + } +} \ No newline at end of file diff --git a/src/main/java/com/guaiguailang/harmony/service/impl/UserServiceImpl.java b/src/main/java/com/guaiguailang/harmony/service/impl/UserServiceImpl.java index b775cc9..b8e12d6 100644 --- a/src/main/java/com/guaiguailang/harmony/service/impl/UserServiceImpl.java +++ b/src/main/java/com/guaiguailang/harmony/service/impl/UserServiceImpl.java @@ -3,7 +3,6 @@ package com.guaiguailang.harmony.service.impl; import cn.dev33.satoken.stp.StpUtil; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.github.yitter.idgen.YitIdHelper; -import com.guaiguailang.harmony.constant.FileUploadFolder; import com.guaiguailang.harmony.domain.dto.ParamUserAdd; import com.guaiguailang.harmony.domain.dto.ParamUserList; import com.guaiguailang.harmony.domain.entity.*; @@ -309,19 +308,10 @@ return ResponseResult.error("删除失败"); */ @Override public String uploadUserAvater(MultipartFile file) { - // 获取用户获取用户信息 + String url = fileUpload.uploadFile(file,file.getName(),"user","用户头像"); Long uid = Long.parseLong(StpUtil.getLoginId().toString()); - UserInfo userInfo = userMapper.getUserById(uid); - // 调用文件上传工具类,传入:文件,保存到的文件夹,文件名 - //设置文件名是为了替换旧的头像文件 - String imgUrl= fileUpload.uploadFile(file, FileUploadFolder.USER_AVATER_FOLDER,userInfo.getUsername()); - if(imgUrl!=null) { - userInfo.setAvatar(imgUrl); - userMapper.updateById(userInfo); - log.info("头像上传成功:" + imgUrl); - return imgUrl; - } - return null; + userMapper.updateUserAvatar(uid,url); + return url; } diff --git a/src/main/java/com/guaiguailang/harmony/utils/FileUpload.java b/src/main/java/com/guaiguailang/harmony/utils/FileUpload.java index e25bbdd..20f6f3a 100644 --- a/src/main/java/com/guaiguailang/harmony/utils/FileUpload.java +++ b/src/main/java/com/guaiguailang/harmony/utils/FileUpload.java @@ -1,6 +1,11 @@ package com.guaiguailang.harmony.utils; +import com.github.yitter.idgen.YitIdHelper; +import com.guaiguailang.harmony.constant.SystemConfigKey; +import com.guaiguailang.harmony.domain.entity.SystemFile; +import com.guaiguailang.harmony.mapper.ConfigMapper; +import com.guaiguailang.harmony.mapper.FileMapper; import jakarta.servlet.ServletContext; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; @@ -8,7 +13,11 @@ import org.springframework.stereotype.Component; import org.springframework.web.multipart.MultipartFile; import java.io.File; +import java.io.FileInputStream; import java.io.IOException; +import java.security.MessageDigest; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; import java.util.UUID; /** @@ -17,20 +26,20 @@ import java.util.UUID; @Component public class FileUpload { - @Value("${server.servlet.context-path}") - private String contextPath; - - @Value("${server.port}") - private String serverPort; - - @Value("${server.address}") - private String serverAddress; - @Autowired - private ServletContext servletContext; + private ConfigMapper configMapper; + @Autowired + private FileMapper fileMapper; + public String uploadFile(MultipartFile file,String fileName,String plate,String description) { + // 校验文件是否重复 + String md5 = UtilMD5.getFileMD5(file); + SystemFile systemFile = fileMapper.getFileByMd5(md5); + if(systemFile!=null){ + return getAccessPath(md5); + } + // 没有上传过该文件,继续操作 - public String uploadFile(MultipartFile file, String folder) { // 获取图片的原始名字 String originalFilename = file.getOriginalFilename(); @@ -39,87 +48,78 @@ public class FileUpload { } // 获取文件的后缀和新文件名 - String ext = "." + originalFilename.substring(originalFilename.lastIndexOf('.') + 1); - String uuid = UUID.randomUUID().toString().replace("-", ""); - String fileName = uuid + ext; + String ext = "." + originalFilename.substring(originalFilename.lastIndexOf('.') + 1);// 扩展名 + + String saveFileName = md5 + ext; // 构建目标文件路径 - String pre = getResourcePath(folder); - String filePath = pre + fileName; + String pre = getResourcePath(); + String filePath = pre + saveFileName; + // 获取文件大小(单位MB) + double fileSize = file.getSize() / (1024.0 * 1024.0);//MB // 上传图片 try { file.transferTo(new File(filePath)); + String url = getAccessPath(md5); // 返回访问链接 - return getAccessPath(folder, fileName); - } catch (IOException e) { - e.printStackTrace(); - } - - return null; - } - - public String uploadFile(MultipartFile file, String folder, String fileName) { - // 获取图片的原始名字 - String originalFilename = file.getOriginalFilename(); - - if (originalFilename == null || originalFilename.isEmpty()) { - throw new IllegalArgumentException("文件名不能为空"); - } - - // 获取文件的后缀和新文件名 - String ext = "." + originalFilename.substring(originalFilename.lastIndexOf('.') + 1); - fileName = fileName + ext; - - // 构建目标文件路径 - String pre = getResourcePath(folder); - String filePath = pre + fileName; - - // 上传图片 - try { - file.transferTo(new File(filePath)); - // 返回访问链接 - return getAccessPath(folder, fileName); + fileMapper.save(YitIdHelper.nextId(),fileName,ext,fileSize,md5,plate,description,filePath,url); + return url; } catch (Exception e) { e.printStackTrace(); } - return null; } - private String getResourcePath(String folder) { + /** + * 获取文件存储路径 + * @return 文件存储路径(末尾包含/) + */ + /** + * 获取文件存储路径 + * @return 文件存储路径(末尾包含/) + */ + private String getResourcePath() { // 获取操作系统的名称 String osName = System.getProperty("os.name"); String win = "win"; - - // 获取项目的根目录 - String projectRoot = System.getProperty("user.dir"); - - // 根据操作系统生成正确的路径 String staticPath; + + // 获取当前日期的年份和月份 + LocalDateTime now = LocalDateTime.now(); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM"); + String datePath = now.format(formatter); + // 保存地址 if (osName.toLowerCase().startsWith(win)) { - staticPath = projectRoot + "\\src\\main\\resources\\static\\" + folder + "\\"; + staticPath = configMapper.getKeyValue(SystemConfigKey.SYS_FILE_SAVE_PATH) + "\\" + datePath.replace("/", "\\") + "\\"; } else { - staticPath = projectRoot + "/src/main/resources/static/" + folder + "/"; + staticPath = configMapper.getKeyValue(SystemConfigKey.SYS_FILE_SAVE_PATH) + "/" + datePath + "/"; } - System.out.println("路径: " + staticPath); - - // 如果目录不存在,就创建目录 + // 创建目录 File dir = new File(staticPath); if (!dir.exists()) { dir.mkdirs(); } - return staticPath; } - private String getAccessPath(String folder, String fileName) { - // 构建访问路径 - return "http://" + serverAddress + ":" + serverPort + contextPath + "static/" + folder + "/" + fileName; + /** + * 获取图片访问路径 + * @param fileMd5 文件名(MD5) + * @return 文件在线访问路径 + */ + public String getAccessPath(String fileMd5) { + String url; + if (System.getProperty("os.name").toLowerCase().startsWith("win")) { + url =configMapper.getKeyValue(SystemConfigKey.SYS_CONFIG_URL_BACK)+"\\upload\\"+fileMd5; + } else { + url =configMapper.getKeyValue(SystemConfigKey.SYS_CONFIG_URL_BACK)+"/upload/"+fileMd5; + } + return url; } diff --git a/src/main/java/com/guaiguailang/harmony/utils/UtilMD5.java b/src/main/java/com/guaiguailang/harmony/utils/UtilMD5.java new file mode 100644 index 0000000..7dfd394 --- /dev/null +++ b/src/main/java/com/guaiguailang/harmony/utils/UtilMD5.java @@ -0,0 +1,51 @@ +package com.guaiguailang.harmony.utils; + +import org.springframework.web.multipart.MultipartFile; + +import java.io.FileInputStream; +import java.io.InputStream; +import java.security.MessageDigest; + +public class UtilMD5 { + public static String getFileMD5(String filePath) { + try { + MessageDigest md5 = MessageDigest.getInstance("MD5"); + FileInputStream fis = new FileInputStream(filePath); + byte[] buffer = new byte[1024]; + int length; + while ((length = fis.read(buffer)) != -1) { + md5.update(buffer, 0, length); + } + byte[] digest = md5.digest(); + StringBuilder sb = new StringBuilder(); + for (byte b : digest) { + sb.append(Integer.toString((b & 0xFF) + 0x100, 16).substring(1)); + } + return sb.toString(); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + // 新增的方法,支持直接对 MultipartFile 获取 MD5 + public static String getFileMD5(MultipartFile file) { + try { + MessageDigest md5 = MessageDigest.getInstance("MD5"); + InputStream is = file.getInputStream(); + byte[] buffer = new byte[1024]; + int length; + while ((length = is.read(buffer)) != -1) { + md5.update(buffer, 0, length); + } + byte[] digest = md5.digest(); + StringBuilder sb = new StringBuilder(); + for (byte b : digest) { + sb.append(Integer.toString((b & 0xFF) + 0x100, 16).substring(1)); + } + return sb.toString(); + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } +} \ No newline at end of file diff --git a/src/main/resources/mapper/ConfigMapper.xml b/src/main/resources/mapper/ConfigMapper.xml new file mode 100644 index 0000000..a0bd451 --- /dev/null +++ b/src/main/resources/mapper/ConfigMapper.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/src/main/resources/static/userAvatar/xrilang.png b/src/main/resources/static/userAvatar/xrilang.png index bbebfd6..2ad8c80 100644 Binary files a/src/main/resources/static/userAvatar/xrilang.png and b/src/main/resources/static/userAvatar/xrilang.png differ