diff --git a/src/main/java/io/github/xxyopen/novel/controller/front/ResourceController.java b/src/main/java/io/github/xxyopen/novel/controller/front/ResourceController.java index 9dbae2f..9bf26b6 100644 --- a/src/main/java/io/github/xxyopen/novel/controller/front/ResourceController.java +++ b/src/main/java/io/github/xxyopen/novel/controller/front/ResourceController.java @@ -5,9 +5,8 @@ import io.github.xxyopen.novel.core.constant.ApiRouterConsts; import io.github.xxyopen.novel.dto.resp.ImgVerifyCodeRespDto; import io.github.xxyopen.novel.service.ResourceService; import lombok.RequiredArgsConstructor; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; import java.io.IOException; @@ -32,4 +31,12 @@ public class ResourceController { return resourceService.getImgVerifyCode(); } + /** + * 图片上传接口 + * */ + @PostMapping("/image") + RestResp uploadImage(@RequestParam("file") MultipartFile file) { + return resourceService.uploadImage(file); + } + } diff --git a/src/main/java/io/github/xxyopen/novel/core/common/constant/ErrorCodeEnum.java b/src/main/java/io/github/xxyopen/novel/core/common/constant/ErrorCodeEnum.java index 8936b5d..e69e7d4 100644 --- a/src/main/java/io/github/xxyopen/novel/core/common/constant/ErrorCodeEnum.java +++ b/src/main/java/io/github/xxyopen/novel/core/common/constant/ErrorCodeEnum.java @@ -92,6 +92,16 @@ public enum ErrorCodeEnum { * */ USER_COMMENTED("A2001","用户已发表评论"), + /** + * 用户上传文件异常 + * */ + USER_UPLOAD_FILE_ERROR("A0700","用户上传文件异常"), + + /** + * 用户上传文件类型不匹配 + * */ + USER_UPLOAD_FILE_TYPE_NOT_MATCH("A0701","用户上传文件类型不匹配"), + /** * 一级宏观错误码,系统执行出错 * */ diff --git a/src/main/java/io/github/xxyopen/novel/core/constant/SystemConfigConsts.java b/src/main/java/io/github/xxyopen/novel/core/constant/SystemConfigConsts.java index a49c15f..3d7b94d 100644 --- a/src/main/java/io/github/xxyopen/novel/core/constant/SystemConfigConsts.java +++ b/src/main/java/io/github/xxyopen/novel/core/constant/SystemConfigConsts.java @@ -32,6 +32,11 @@ public class SystemConfigConsts { * */ public static final String NOVEL_ADMIN_KEY = "admin"; + /** + * 图片上传目录 + * */ + public static final String IMAGE_UPLOAD_DIRECTORY = "/image/"; + /** * 常量类实例化异常信息 * */ diff --git a/src/main/java/io/github/xxyopen/novel/core/json/deserializer/GlobalJsonDeserializer.java b/src/main/java/io/github/xxyopen/novel/core/json/deserializer/GlobalJsonDeserializer.java index 5276406..b20d046 100644 --- a/src/main/java/io/github/xxyopen/novel/core/json/deserializer/GlobalJsonDeserializer.java +++ b/src/main/java/io/github/xxyopen/novel/core/json/deserializer/GlobalJsonDeserializer.java @@ -1,6 +1,5 @@ package io.github.xxyopen.novel.core.json.deserializer; -import com.fasterxml.jackson.core.JacksonException; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; @@ -25,7 +24,7 @@ public class GlobalJsonDeserializer { public static class StringDeserializer extends JsonDeserializer { @Override - public String deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JacksonException { + public String deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException { return jsonParser.getValueAsString() .replace("<", "<") .replace(">", ">"); diff --git a/src/main/java/io/github/xxyopen/novel/service/ResourceService.java b/src/main/java/io/github/xxyopen/novel/service/ResourceService.java index f28622b..35c6d1a 100644 --- a/src/main/java/io/github/xxyopen/novel/service/ResourceService.java +++ b/src/main/java/io/github/xxyopen/novel/service/ResourceService.java @@ -2,6 +2,7 @@ package io.github.xxyopen.novel.service; import io.github.xxyopen.novel.core.common.resp.RestResp; import io.github.xxyopen.novel.dto.resp.ImgVerifyCodeRespDto; +import org.springframework.web.multipart.MultipartFile; import java.io.IOException; @@ -16,7 +17,15 @@ public interface ResourceService { /** * 获取图片验证码 * + * @throws IOException 验证码图片生成失败 * @return Base64编码的图片 */ RestResp getImgVerifyCode() throws IOException; + + /** + * 图片上传 + * @param file 需要上传的图片 + * @return 图片访问路径 + * */ + RestResp uploadImage(MultipartFile file); } diff --git a/src/main/java/io/github/xxyopen/novel/service/impl/ResourceServiceImpl.java b/src/main/java/io/github/xxyopen/novel/service/impl/ResourceServiceImpl.java index 6eedc07..1b5ea7c 100644 --- a/src/main/java/io/github/xxyopen/novel/service/impl/ResourceServiceImpl.java +++ b/src/main/java/io/github/xxyopen/novel/service/impl/ResourceServiceImpl.java @@ -1,14 +1,27 @@ package io.github.xxyopen.novel.service.impl; import com.baomidou.mybatisplus.core.toolkit.IdWorker; +import io.github.xxyopen.novel.core.common.constant.ErrorCodeEnum; +import io.github.xxyopen.novel.core.common.exception.BusinessException; import io.github.xxyopen.novel.core.common.resp.RestResp; +import io.github.xxyopen.novel.core.constant.SystemConfigConsts; import io.github.xxyopen.novel.dto.resp.ImgVerifyCodeRespDto; import io.github.xxyopen.novel.manager.VerifyCodeManager; import io.github.xxyopen.novel.service.ResourceService; import lombok.RequiredArgsConstructor; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; +import javax.imageio.ImageIO; +import java.io.File; import java.io.IOException; +import java.nio.file.Files; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Objects; /** * 资源(图片/视频/文档)相关服务实现类 @@ -18,10 +31,14 @@ import java.io.IOException; */ @Service @RequiredArgsConstructor +@Slf4j public class ResourceServiceImpl implements ResourceService { private final VerifyCodeManager verifyCodeManager; + @Value("${novel.file.upload.path}") + private String fileUploadPath; + @Override public RestResp getImgVerifyCode() throws IOException { String sessionId = IdWorker.get32UUID(); @@ -31,4 +48,32 @@ public class ResourceServiceImpl implements ResourceService { .build()); } + @SneakyThrows + @Override + public RestResp uploadImage(MultipartFile file) { + LocalDateTime now = LocalDateTime.now(); + String savePath = + SystemConfigConsts.IMAGE_UPLOAD_DIRECTORY + + now.format(DateTimeFormatter.ofPattern("yyyy")) + File.separator + + now.format(DateTimeFormatter.ofPattern("MM")) + File.separator + + now.format(DateTimeFormatter.ofPattern("dd")); + String oriName = file.getOriginalFilename(); + assert oriName != null; + String saveFileName = IdWorker.get32UUID() + oriName.substring(oriName.lastIndexOf(".")); + File saveFile = new File(fileUploadPath + savePath, saveFileName); + if (!saveFile.getParentFile().exists()) { + boolean isSuccess = saveFile.getParentFile().mkdirs(); + if (!isSuccess) { + throw new BusinessException(ErrorCodeEnum.USER_UPLOAD_FILE_ERROR); + } + } + file.transferTo(saveFile); + if (Objects.isNull(ImageIO.read(saveFile))) { + // 上传的文件不是图片 + Files.delete(saveFile.toPath()); + throw new BusinessException(ErrorCodeEnum.USER_UPLOAD_FILE_TYPE_NOT_MATCH); + } + return RestResp.ok(savePath + File.separator + saveFileName); + } + } diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 49bfd6f..0dd1cc8 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -61,7 +61,11 @@ novel: # 排除链接 excludes: - /system/notice/* - + file: + # 文件上传配置 + upload: + # 上传路径 + path: /var/upload