diff --git a/pom.xml b/pom.xml index 44b6c27..877bba6 100644 --- a/pom.xml +++ b/pom.xml @@ -39,7 +39,11 @@ pom import - + + com.github.pagehelper + pagehelper-spring-boot-starter + 1.4.6 + diff --git a/timeline-component-common/pom.xml b/timeline-component-common/pom.xml index 138b64a..8d00550 100644 --- a/timeline-component-common/pom.xml +++ b/timeline-component-common/pom.xml @@ -39,6 +39,17 @@ 3.5.17 compile + + com.github.pagehelper + pagehelper-spring-boot-starter + 1.4.6 + + + com.alibaba + fastjson + 1.2.83 + compile + diff --git a/timeline-component-common/src/main/java/com/timeline/aop/RequestLogAspect.java b/timeline-component-common/src/main/java/com/timeline/common/aop/RequestLogAspect.java similarity index 98% rename from timeline-component-common/src/main/java/com/timeline/aop/RequestLogAspect.java rename to timeline-component-common/src/main/java/com/timeline/common/aop/RequestLogAspect.java index 7ec14b4..f78a358 100644 --- a/timeline-component-common/src/main/java/com/timeline/aop/RequestLogAspect.java +++ b/timeline-component-common/src/main/java/com/timeline/common/aop/RequestLogAspect.java @@ -1,4 +1,4 @@ -package com.timeline.aop; +package com.timeline.common.aop; import jakarta.servlet.http.HttpServletRequest; import lombok.extern.slf4j.Slf4j; diff --git a/timeline-component-common/src/main/java/com/timeline/common/config/PageHelperConfig.java b/timeline-component-common/src/main/java/com/timeline/common/config/PageHelperConfig.java new file mode 100644 index 0000000..f44f7ed --- /dev/null +++ b/timeline-component-common/src/main/java/com/timeline/common/config/PageHelperConfig.java @@ -0,0 +1,26 @@ +package com.timeline.common.config; + +import com.github.pagehelper.PageInterceptor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import java.util.Properties; + +@Configuration +public class PageHelperConfig { + @Bean(name = "pageHelper") + public PageInterceptor pageInterceptor() { + PageInterceptor interceptor = new PageInterceptor(); + Properties properties = new Properties(); + // 配置数据库方言 + properties.setProperty("helperDialect", "mysql"); + // 分页合理化参数,默认值为false + properties.setProperty("reasonable", "true"); + // 支持通过Mapper接口参数来传递分页参数 + properties.setProperty("supportMethodsArguments", "true"); + // always总是返回PageInfo类型 + properties.setProperty("returnPageInfo", "check"); + interceptor.setProperties(properties); + return interceptor; + } +} diff --git a/timeline-component-common/src/main/java/com/timeline/constants/CommonConstants.java b/timeline-component-common/src/main/java/com/timeline/common/constants/CommonConstants.java similarity index 79% rename from timeline-component-common/src/main/java/com/timeline/constants/CommonConstants.java rename to timeline-component-common/src/main/java/com/timeline/common/constants/CommonConstants.java index c5bde89..77f36e6 100644 --- a/timeline-component-common/src/main/java/com/timeline/constants/CommonConstants.java +++ b/timeline-component-common/src/main/java/com/timeline/common/constants/CommonConstants.java @@ -1,4 +1,4 @@ -package com.timeline.constants; +package com.timeline.common.constants; public class CommonConstants { private static final int RELATION_USER_AND_STORY = 1; @@ -9,4 +9,8 @@ public class CommonConstants { public static final int RELATION_STORY_ITEM_AND_COVER = 6; public static final int STORY_ITEM_IS_ROOT = 1; public static final int STORY_ITEM_IS_NOT_ROOT = 0; + + + public static final int DELETED = 1; + public static final int NOT_DELETED = 0; } diff --git a/timeline-component-common/src/main/java/com/timeline/dto/CommonRelationDTO.java b/timeline-component-common/src/main/java/com/timeline/common/dto/CommonRelationDTO.java similarity index 91% rename from timeline-component-common/src/main/java/com/timeline/dto/CommonRelationDTO.java rename to timeline-component-common/src/main/java/com/timeline/common/dto/CommonRelationDTO.java index 46d7851..379dfb2 100644 --- a/timeline-component-common/src/main/java/com/timeline/dto/CommonRelationDTO.java +++ b/timeline-component-common/src/main/java/com/timeline/common/dto/CommonRelationDTO.java @@ -1,4 +1,4 @@ -package com.timeline.dto; +package com.timeline.common.dto; import lombok.Data; diff --git a/timeline-component-common/src/main/java/com/timeline/common/dto/PageResult.java b/timeline-component-common/src/main/java/com/timeline/common/dto/PageResult.java new file mode 100644 index 0000000..97e19cd --- /dev/null +++ b/timeline-component-common/src/main/java/com/timeline/common/dto/PageResult.java @@ -0,0 +1,23 @@ +package com.timeline.common.dto; + +import com.github.pagehelper.PageInfo; +import lombok.AllArgsConstructor; +import lombok.Data; + +import java.util.List; + +@Data +@AllArgsConstructor +public class PageResult { + private long total; + private int pageNum; + private int pageSize; + private int pages; + private List list; + + public static PageResult of(List list) { + PageInfo pageInfo = new PageInfo<>(list); + return new PageResult(pageInfo.getTotal(), pageInfo.getPageNum(), + pageInfo.getPageSize(), pageInfo.getPages(), pageInfo.getList()); + } +} diff --git a/timeline-component-common/src/main/java/com/timeline/enums/RelationTypeEnum.java b/timeline-component-common/src/main/java/com/timeline/common/enums/RelationTypeEnum.java similarity index 50% rename from timeline-component-common/src/main/java/com/timeline/enums/RelationTypeEnum.java rename to timeline-component-common/src/main/java/com/timeline/common/enums/RelationTypeEnum.java index a6d4e62..a1f12fc 100644 --- a/timeline-component-common/src/main/java/com/timeline/enums/RelationTypeEnum.java +++ b/timeline-component-common/src/main/java/com/timeline/common/enums/RelationTypeEnum.java @@ -1,4 +1,4 @@ -package com.timeline.enums; +package com.timeline.common.enums; public enum RelationTypeEnum { diff --git a/timeline-component-common/src/main/java/com/timeline/exception/CustomException.java b/timeline-component-common/src/main/java/com/timeline/common/exception/CustomException.java similarity index 89% rename from timeline-component-common/src/main/java/com/timeline/exception/CustomException.java rename to timeline-component-common/src/main/java/com/timeline/common/exception/CustomException.java index 597dc21..6abcb18 100644 --- a/timeline-component-common/src/main/java/com/timeline/exception/CustomException.java +++ b/timeline-component-common/src/main/java/com/timeline/common/exception/CustomException.java @@ -1,6 +1,6 @@ -package com.timeline.exception; +package com.timeline.common.exception; -import com.timeline.response.ResponseEnum; +import com.timeline.common.response.ResponseEnum; public class CustomException extends RuntimeException { private final int code; diff --git a/timeline-component-common/src/main/java/com/timeline/handler/GlobalExceptionHandler.java b/timeline-component-common/src/main/java/com/timeline/common/handler/GlobalExceptionHandler.java similarity index 78% rename from timeline-component-common/src/main/java/com/timeline/handler/GlobalExceptionHandler.java rename to timeline-component-common/src/main/java/com/timeline/common/handler/GlobalExceptionHandler.java index e193caa..21f3b4b 100644 --- a/timeline-component-common/src/main/java/com/timeline/handler/GlobalExceptionHandler.java +++ b/timeline-component-common/src/main/java/com/timeline/common/handler/GlobalExceptionHandler.java @@ -1,8 +1,8 @@ -package com.timeline.handler; +package com.timeline.common.handler; -import com.timeline.exception.CustomException; -import com.timeline.response.ResponseEntity; -import com.timeline.response.ResponseEnum; +import com.timeline.common.exception.CustomException; +import com.timeline.common.response.ResponseEntity; +import com.timeline.common.response.ResponseEnum; import org.springframework.web.bind.annotation.ExceptionHandler; import org.springframework.web.bind.annotation.RestControllerAdvice; diff --git a/timeline-component-common/src/main/java/com/timeline/response/ResponseEntity.java b/timeline-component-common/src/main/java/com/timeline/common/response/ResponseEntity.java similarity index 95% rename from timeline-component-common/src/main/java/com/timeline/response/ResponseEntity.java rename to timeline-component-common/src/main/java/com/timeline/common/response/ResponseEntity.java index 386095e..321517b 100644 --- a/timeline-component-common/src/main/java/com/timeline/response/ResponseEntity.java +++ b/timeline-component-common/src/main/java/com/timeline/common/response/ResponseEntity.java @@ -1,4 +1,4 @@ -package com.timeline.response; +package com.timeline.common.response; import lombok.AllArgsConstructor; import lombok.Data; diff --git a/timeline-component-common/src/main/java/com/timeline/response/ResponseEnum.java b/timeline-component-common/src/main/java/com/timeline/common/response/ResponseEnum.java similarity index 85% rename from timeline-component-common/src/main/java/com/timeline/response/ResponseEnum.java rename to timeline-component-common/src/main/java/com/timeline/common/response/ResponseEnum.java index 757f54c..60e821b 100644 --- a/timeline-component-common/src/main/java/com/timeline/response/ResponseEnum.java +++ b/timeline-component-common/src/main/java/com/timeline/common/response/ResponseEnum.java @@ -1,4 +1,4 @@ -package com.timeline.response; +package com.timeline.common.response; import lombok.AllArgsConstructor; import lombok.Getter; @@ -25,7 +25,10 @@ public enum ResponseEnum { NOT_IMPLEMENTED(501, "功能未实现"), BAD_GATEWAY(502, "网关错误"), SERVICE_UNAVAILABLE(503, "服务不可用"), - GATEWAY_TIMEOUT(504, "网关超时"); + GATEWAY_TIMEOUT(504, "网关超时"), + + // 操作错误 + SEARCH_ERROR(4001, "查询数据库错误"); private final int code; private final String message; diff --git a/timeline-component-common/src/main/java/com/timeline/common/utils/CommonUtils.java b/timeline-component-common/src/main/java/com/timeline/common/utils/CommonUtils.java new file mode 100644 index 0000000..0c051f5 --- /dev/null +++ b/timeline-component-common/src/main/java/com/timeline/common/utils/CommonUtils.java @@ -0,0 +1,20 @@ +package com.timeline.common.utils; + +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +public class CommonUtils { + public static String calculateFileHash(MultipartFile file) throws IOException, NoSuchAlgorithmException { + MessageDigest digest = MessageDigest.getInstance("SHA-256"); + byte[] fileBytes = file.getBytes(); + byte[] hashBytes = digest.digest(fileBytes); + StringBuilder sb = new StringBuilder(); + for (byte b : hashBytes) { + sb.append(String.format("%02x", b)); + } + return sb.toString(); + } +} diff --git a/timeline-component-common/src/main/java/com/timeline/utils/IdUtils.java b/timeline-component-common/src/main/java/com/timeline/common/utils/IdUtils.java similarity index 93% rename from timeline-component-common/src/main/java/com/timeline/utils/IdUtils.java rename to timeline-component-common/src/main/java/com/timeline/common/utils/IdUtils.java index cbc3d60..4a5184d 100644 --- a/timeline-component-common/src/main/java/com/timeline/utils/IdUtils.java +++ b/timeline-component-common/src/main/java/com/timeline/common/utils/IdUtils.java @@ -1,4 +1,4 @@ -package com.timeline.utils; +package com.timeline.common.utils; import java.util.UUID; diff --git a/timeline-component-common/src/main/java/com/timeline/common/utils/PageUtils.java b/timeline-component-common/src/main/java/com/timeline/common/utils/PageUtils.java new file mode 100644 index 0000000..c757f09 --- /dev/null +++ b/timeline-component-common/src/main/java/com/timeline/common/utils/PageUtils.java @@ -0,0 +1,49 @@ +package com.timeline.common.utils; + +import com.github.pagehelper.PageHelper; +import com.github.pagehelper.PageInfo; +import com.timeline.common.exception.CustomException; +import com.timeline.common.response.ResponseEnum; +import lombok.extern.slf4j.Slf4j; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Slf4j +public class PageUtils { + public PageUtils() { + } + + public static Map pageQuery(Integer pageNum, Integer pageSize, Class clas, String methodName, Object params, String listKey) { + Map pageResult = new HashMap(); + if (pageNum == null) { + pageNum = 0; + } + + if (pageSize == null) { + pageSize = 0; + } + + try { + if (pageNum >= 1 && pageSize >= 1) { + PageHelper.startPage(pageNum, pageSize); + List list = (List)ReflectUtils.call(clas, methodName, params); + PageInfo pageInfo = new PageInfo(list); + pageResult.put("pageNumber", pageInfo.getPageNum()); + pageResult.put("pageSize", pageInfo.getPageSize()); + pageResult.put("total", pageInfo.getTotal()); + pageResult.put("pages", pageInfo.getPages()); + pageResult.put(listKey, pageInfo.getList()); + return pageResult; + } else { + List list = (List)ReflectUtils.call(clas, methodName, params); + pageResult.put(listKey, list); + return pageResult; + } + } catch (Exception e) { + log.error("查询失败", e); + throw new CustomException(ResponseEnum.SEARCH_ERROR); + } + } +} diff --git a/timeline-component-common/src/main/java/com/timeline/common/utils/ReflectUtils.java b/timeline-component-common/src/main/java/com/timeline/common/utils/ReflectUtils.java new file mode 100644 index 0000000..7cccbb6 --- /dev/null +++ b/timeline-component-common/src/main/java/com/timeline/common/utils/ReflectUtils.java @@ -0,0 +1,58 @@ +package com.timeline.common.utils; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; +import org.springframework.util.StringUtils; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Map; + +public class ReflectUtils { + public ReflectUtils() { + } + + public static Object persistenceData(String entityPath, String persisPath, String methodName, Map params) throws Exception { + Object result = null; + + try { + if (!StringUtils.isEmpty(entityPath) && !StringUtils.isEmpty(persisPath)) { + Class entityClass = Class.forName(entityPath); + Class persisClass = Class.forName(persisPath); + Object daoBean = SpringContextUtils.getBean(persisClass); + Object o = JSONObject.toJavaObject(JSON.parseObject(JSONObject.toJSONString(params)), entityClass); + Method method = persisClass.getMethod(methodName, entityClass); + result = method.invoke(daoBean, o); + return result; + } else { + return null; + } + } catch (Exception e) { + throw e; + } + } + + public static Object call(Class clas, String methodName, Object params) throws Exception { + Object bean = SpringContextUtils.getBean(clas); + Method method = clas.getMethod(methodName, Map.class); + Object result = method.invoke(bean, params); + return result; + } + + public static Object call(String className, String methodName, String parameterType, JSONObject parameter) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, ClassNotFoundException { + Class clas = Class.forName(className); + Class parameterTypeClass = Class.forName(parameterType); + Object daoBean = SpringContextUtils.getBean(clas); + Object o = JSONObject.toJavaObject(parameter, parameterTypeClass); + Method method = clas.getMethod(methodName, parameterTypeClass); + return method.invoke(daoBean, o); + } + + public static Object call(String className, String methodName, String parameterType, Object parameter) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException, ClassNotFoundException { + Class clas = Class.forName(className); + Class parameterTypeClass = Class.forName(parameterType); + Object daoBean = SpringContextUtils.getBean(clas); + Method method = clas.getMethod(methodName, parameterTypeClass); + return method.invoke(daoBean, parameter); + } +} diff --git a/timeline-component-common/src/main/java/com/timeline/common/utils/SpringContextUtils.java b/timeline-component-common/src/main/java/com/timeline/common/utils/SpringContextUtils.java new file mode 100644 index 0000000..b169cbb --- /dev/null +++ b/timeline-component-common/src/main/java/com/timeline/common/utils/SpringContextUtils.java @@ -0,0 +1,30 @@ +package com.timeline.common.utils; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + +@Component +public class SpringContextUtils implements ApplicationContextAware { + private static ApplicationContext applicationContext; + + public SpringContextUtils() { + } + + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + SpringContextUtils.applicationContext = applicationContext; + } + + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + public static T getBean(String name) throws BeansException { + return (T)applicationContext.getBean(name); + } + + public static T getBean(Class clz) throws BeansException { + return (T)applicationContext.getBean(clz); + } +} diff --git a/timeline-component-common/src/main/java/com/timeline/common/vo/CommonVo.java b/timeline-component-common/src/main/java/com/timeline/common/vo/CommonVo.java new file mode 100644 index 0000000..3962eaa --- /dev/null +++ b/timeline-component-common/src/main/java/com/timeline/common/vo/CommonVo.java @@ -0,0 +1,9 @@ +package com.timeline.common.vo; + +import lombok.Data; + +@Data +public class CommonVo { + private Integer pageSize; + private Integer current; +} diff --git a/timeline-file-service/pom.xml b/timeline-file-service/pom.xml index 66d99e7..2b0c885 100644 --- a/timeline-file-service/pom.xml +++ b/timeline-file-service/pom.xml @@ -77,6 +77,10 @@ lombok true + + org.springframework.cloud + spring-cloud-openfeign-core + diff --git a/timeline-file-service/src/main/java/com/timeline/file/controller/FileController.java b/timeline-file-service/src/main/java/com/timeline/file/controller/FileController.java index ff34eb5..51b50b8 100644 --- a/timeline-file-service/src/main/java/com/timeline/file/controller/FileController.java +++ b/timeline-file-service/src/main/java/com/timeline/file/controller/FileController.java @@ -1,21 +1,22 @@ package com.timeline.file.controller; +import com.timeline.file.entity.ImageInfo; import com.timeline.file.service.FileService; -import com.timeline.file.service.impl.FileServiceImpl; import com.timeline.file.vo.ImageInfoVo; -import com.timeline.response.ResponseEntity; +import com.timeline.common.response.ResponseEntity; import jakarta.servlet.http.HttpServletResponse; import lombok.extern.slf4j.Slf4j; import org.apache.commons.compress.utils.IOUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.cloud.openfeign.SpringQueryMap; import org.springframework.http.MediaType; -import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import java.io.InputStream; import java.util.ArrayList; import java.util.List; +import java.util.Map; @Slf4j @RestController @@ -47,13 +48,13 @@ public class FileController { fileService.saveFileMetadata(imageInfoVo); return ResponseEntity.success("上传成功"); } - @PostMapping("/upload-cover") - public ResponseEntity uploadCover(@RequestPart("cover") MultipartFile cover) throws Throwable { - String objectKey = fileService.uploadCover(cover); + @PostMapping("/upload-image") + public ResponseEntity uploadCover(@RequestPart("image") MultipartFile image) throws Throwable { + String objectKey = fileService.uploadCover(image); return ResponseEntity.success(objectKey); } - @RequestMapping(value = "/download/cover/{coverInstanceId}", method = RequestMethod.GET, produces = MediaType.IMAGE_JPEG_VALUE) + @RequestMapping(value = "/image/{coverInstanceId}", method = RequestMethod.GET, produces = MediaType.IMAGE_JPEG_VALUE) public void downloadCover(@PathVariable String coverInstanceId, HttpServletResponse response) throws Throwable { log.info("downloadCover"); InputStream inputStream = fileService.downloadCover(coverInstanceId); @@ -100,4 +101,15 @@ public class FileController { fileService.removeImageFromStoryItem(imageInstanceId, storyItemId); return ResponseEntity.success("图片已从故事项中移除"); } + @GetMapping("/image/list") + public ResponseEntity getImagesListByOwnerId(@SpringQueryMap ImageInfoVo imageInfoVo) throws Throwable { + imageInfoVo.setOwnerId("9999"); + Map images = fileService.getImagesListByOwnerId(imageInfoVo); + return ResponseEntity.success(images); + } + @DeleteMapping("/image/{imageInstanceId}") + public ResponseEntity deleteImage(@PathVariable String imageInstanceId) throws Throwable { + fileService.deleteImage(imageInstanceId); + return ResponseEntity.success("图片已删除"); + } } diff --git a/timeline-file-service/src/main/java/com/timeline/file/dao/CommonRelationMapper.java b/timeline-file-service/src/main/java/com/timeline/file/dao/CommonRelationMapper.java index 431b36a..f905f23 100644 --- a/timeline-file-service/src/main/java/com/timeline/file/dao/CommonRelationMapper.java +++ b/timeline-file-service/src/main/java/com/timeline/file/dao/CommonRelationMapper.java @@ -1,6 +1,6 @@ package com.timeline.file.dao; -import com.timeline.dto.CommonRelationDTO; +import com.timeline.common.dto.CommonRelationDTO; import org.apache.ibatis.annotations.Mapper; import java.util.List; diff --git a/timeline-file-service/src/main/java/com/timeline/file/dao/FileHashMapper.java b/timeline-file-service/src/main/java/com/timeline/file/dao/FileHashMapper.java new file mode 100644 index 0000000..de11120 --- /dev/null +++ b/timeline-file-service/src/main/java/com/timeline/file/dao/FileHashMapper.java @@ -0,0 +1,15 @@ +package com.timeline.file.dao; + +import com.timeline.file.entity.FileHash; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +@Mapper +public interface FileHashMapper { + void insertFileHash(FileHash fileHash); + List getFileHashByFileHash(String fileHash); + List getFileHashByInstanceId(String instanceId); + List getOtherFileHashByInstanceId(String instanceId); + void deleteFileHash(String instanceId); +} diff --git a/timeline-file-service/src/main/java/com/timeline/file/dao/ImageInfoMapper.java b/timeline-file-service/src/main/java/com/timeline/file/dao/ImageInfoMapper.java index 36fc97a..2b08722 100644 --- a/timeline-file-service/src/main/java/com/timeline/file/dao/ImageInfoMapper.java +++ b/timeline-file-service/src/main/java/com/timeline/file/dao/ImageInfoMapper.java @@ -1,11 +1,18 @@ package com.timeline.file.dao; import com.timeline.file.entity.ImageInfo; +import com.timeline.file.vo.ImageInfoVo; import org.apache.ibatis.annotations.Mapper; +import java.util.List; +import java.util.Map; + @Mapper public interface ImageInfoMapper { void insert(ImageInfo imageInfo); + void update(ImageInfo imageInfo); String selectObjectKeyById(String objectKey); void delete(String objectKey); + List selectListByOwnerId(Map map); + ImageInfo selectByInstanceId(String instanceId); } diff --git a/timeline-file-service/src/main/java/com/timeline/file/entity/FileHash.java b/timeline-file-service/src/main/java/com/timeline/file/entity/FileHash.java new file mode 100644 index 0000000..bfb445a --- /dev/null +++ b/timeline-file-service/src/main/java/com/timeline/file/entity/FileHash.java @@ -0,0 +1,18 @@ +package com.timeline.file.entity; + +import lombok.Data; + +@Data +public class FileHash { + private Integer id; + private String instanceId; + private String hashValue; + private Integer isDeleted; + + public FileHash(String instanceId, String hashValue) { + this.id = null; + this.instanceId = instanceId; + this.hashValue = hashValue; + this.isDeleted = 0; + } +} diff --git a/timeline-file-service/src/main/java/com/timeline/file/entity/ImageInfo.java b/timeline-file-service/src/main/java/com/timeline/file/entity/ImageInfo.java index c7759e1..2340105 100644 --- a/timeline-file-service/src/main/java/com/timeline/file/entity/ImageInfo.java +++ b/timeline-file-service/src/main/java/com/timeline/file/entity/ImageInfo.java @@ -15,4 +15,5 @@ public class ImageInfo { private String contentType; private String userId; private Integer isDeleted; + private LocalDateTime updateTime; } diff --git a/timeline-file-service/src/main/java/com/timeline/file/service/FileService.java b/timeline-file-service/src/main/java/com/timeline/file/service/FileService.java index 48c1403..9283d8e 100644 --- a/timeline-file-service/src/main/java/com/timeline/file/service/FileService.java +++ b/timeline-file-service/src/main/java/com/timeline/file/service/FileService.java @@ -8,6 +8,7 @@ import org.springframework.web.multipart.MultipartFile; import java.io.InputStream; import java.util.ArrayList; import java.util.List; +import java.util.Map; @Service public interface FileService { @@ -23,4 +24,5 @@ public interface FileService { ArrayList getAllImageUrls(List images) throws Throwable; String uploadCover(MultipartFile cover) throws Throwable; InputStream downloadCover(String coverKey) throws Throwable; + Map getImagesListByOwnerId(ImageInfoVo imageInfoVo); } diff --git a/timeline-file-service/src/main/java/com/timeline/file/service/impl/FileServiceImpl.java b/timeline-file-service/src/main/java/com/timeline/file/service/impl/FileServiceImpl.java index 883f718..aa078ad 100644 --- a/timeline-file-service/src/main/java/com/timeline/file/service/impl/FileServiceImpl.java +++ b/timeline-file-service/src/main/java/com/timeline/file/service/impl/FileServiceImpl.java @@ -1,13 +1,18 @@ package com.timeline.file.service.impl; -import com.timeline.exception.CustomException; +import com.timeline.common.constants.CommonConstants; +import com.timeline.common.exception.CustomException; +import com.timeline.common.utils.CommonUtils; +import com.timeline.common.utils.PageUtils; import com.timeline.file.config.MinioConfig; import com.timeline.file.dao.CommonRelationMapper; +import com.timeline.file.dao.FileHashMapper; import com.timeline.file.dao.ImageInfoMapper; +import com.timeline.file.entity.FileHash; import com.timeline.file.entity.ImageInfo; import com.timeline.file.service.FileService; import com.timeline.file.vo.ImageInfoVo; -import com.timeline.utils.IdUtils; +import com.timeline.common.utils.IdUtils; import io.minio.*; import io.minio.errors.MinioException; import io.minio.http.Method; @@ -18,8 +23,7 @@ import org.springframework.web.multipart.MultipartFile; import java.io.InputStream; import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.List; +import java.util.*; @Slf4j @Service @@ -32,6 +36,8 @@ public class FileServiceImpl implements FileService { @Autowired private CommonRelationMapper commonRelationMapper; @Autowired + private FileHashMapper fileHashMapper; + @Autowired public FileServiceImpl(MinioClient minioClient, MinioConfig minioConfig) { this.minioClient = minioClient; this.minioConfig = minioConfig; @@ -96,16 +102,26 @@ public class FileServiceImpl implements FileService { } @Override - public void deleteImage(String objectKey) throws Throwable { + public void deleteImage(String instanceId) throws Throwable { try { - // 删除 MinIO 中的对象 - minioClient.removeObject(RemoveObjectArgs.builder() - .bucket(minioConfig.getBucketName()) - .object(objectKey) - .build()); + List otherFileHashByInstanceId = fileHashMapper.getOtherFileHashByInstanceId(instanceId); + ImageInfo imageInfo = imageInfoMapper.selectByInstanceId(instanceId); + if (otherFileHashByInstanceId != null && !otherFileHashByInstanceId.isEmpty()) { - // 删除 MySQL 记录 - imageInfoMapper.delete(objectKey); + } else { + // 不存在其他image_info使用则删除 MinIO 中的对象 + minioClient.removeObject(RemoveObjectArgs.builder() + .bucket(minioConfig.getBucketName()) + .object(imageInfo.getObjectKey()) + .build()); + } + // 删除file_hash + fileHashMapper.deleteFileHash(instanceId); + + // 删除image_info + imageInfo.setIsDeleted(CommonConstants.DELETED); + imageInfo.setUpdateTime(LocalDateTime.now()); + imageInfoMapper.update(imageInfo); } catch (Exception e) { log.error("删除图片失败", e); throw new CustomException(500, "删除图片失败"); @@ -149,25 +165,33 @@ public class FileServiceImpl implements FileService { } @Override - public String uploadCover(MultipartFile cover) throws Throwable { - String fileName = "cover-" + IdUtils.randomUuidUpper() + ".jpg"; - // 1. 上传到 MinIO - minioClient.putObject(PutObjectArgs.builder() - .bucket(minioConfig.getBucketName()) - .object(fileName) - .stream(cover.getInputStream(), cover.getSize(), -1) - .contentType(cover.getContentType()) - .build()); - + public String uploadCover(MultipartFile image) throws Throwable { + String suffix = Objects.requireNonNull(image.getOriginalFilename()).substring(image.getOriginalFilename().lastIndexOf(".")); + String hash = CommonUtils.calculateFileHash(image); + String objectKey = hash + suffix; + log.info("上传图片的ObjectKey值为:{}", objectKey); + List hashByFileHash = fileHashMapper.getFileHashByFileHash(hash); // 2. 保存元数据到 MySQL ImageInfo imageInfo = new ImageInfo(); imageInfo.setInstanceId(IdUtils.randomUuidUpper()); - imageInfo.setObjectKey(fileName); - imageInfo.setImageName(fileName); - imageInfo.setContentType(cover.getContentType()); - imageInfo.setSize(cover.getSize()); + imageInfo.setObjectKey(objectKey); + imageInfo.setImageName(image.getOriginalFilename()); + imageInfo.setContentType(image.getContentType()); + imageInfo.setSize(image.getSize()); imageInfo.setUserId("9999"); imageInfo.setUploadTime(LocalDateTime.now()); + if (hashByFileHash != null && !hashByFileHash.isEmpty()) { + log.info("当前文件已存在,不进行minio文件上传"); + } else { + // 1. 上传到 MinIO + minioClient.putObject(PutObjectArgs.builder() + .bucket(minioConfig.getBucketName()) + .object(objectKey) + .stream(image.getInputStream(), image.getSize(), -1) + .contentType(image.getContentType()) + .build()); + } + fileHashMapper.insertFileHash(new FileHash(imageInfo.getInstanceId(), hash)); imageInfoMapper.insert(imageInfo); return imageInfo.getInstanceId(); @@ -182,4 +206,13 @@ public class FileServiceImpl implements FileService { .object(objectKey) .build()); } + + @Override + public Map getImagesListByOwnerId(ImageInfoVo imageInfoVo) { + HashMap map = new HashMap<>(); + map.put("ownerId", imageInfoVo.getOwnerId()); + Map resultMap = PageUtils.pageQuery(imageInfoVo.getCurrent(), imageInfoVo.getPageSize(), ImageInfoMapper.class, "selectListByOwnerId", + map, "list"); + return resultMap; + } } diff --git a/timeline-file-service/src/main/java/com/timeline/file/vo/ImageInfoVo.java b/timeline-file-service/src/main/java/com/timeline/file/vo/ImageInfoVo.java index da2c8e3..c783b61 100644 --- a/timeline-file-service/src/main/java/com/timeline/file/vo/ImageInfoVo.java +++ b/timeline-file-service/src/main/java/com/timeline/file/vo/ImageInfoVo.java @@ -1,12 +1,14 @@ package com.timeline.file.vo; +import com.timeline.common.vo.CommonVo; import lombok.Data; @Data -public class ImageInfoVo { +public class ImageInfoVo extends CommonVo { private String objectKey; private String imageName; private String contentType; private Long size; private String instanceId; + private String ownerId; } diff --git a/timeline-file-service/src/main/resources/application.properties b/timeline-file-service/src/main/resources/application.properties index af387c0..2633cae 100644 --- a/timeline-file-service/src/main/resources/application.properties +++ b/timeline-file-service/src/main/resources/application.properties @@ -13,7 +13,10 @@ minio.bucketName=timeline-test mybatis.mapper-locations=classpath:mapper/*.xml mybatis.type-aliases-package=com.timeline.file.entity +mybatis.configuration.mapUnderscoreToCamelCase=true + + server.port=30002 spring.servlet.multipart.enabled=true spring.servlet.multipart.max-file-size=10MB -spring.servlet.multipart.max-request-size=10MB \ No newline at end of file +spring.servlet.multipart.max-request-size=10MB diff --git a/timeline-file-service/src/main/resources/com/timeline/file/dao/FileHashMapper.xml b/timeline-file-service/src/main/resources/com/timeline/file/dao/FileHashMapper.xml new file mode 100644 index 0000000..c72fdc3 --- /dev/null +++ b/timeline-file-service/src/main/resources/com/timeline/file/dao/FileHashMapper.xml @@ -0,0 +1,25 @@ + + + + + + INSERT INTO file_hash (instance_id, hash_value, is_deleted) + VALUES (#{instanceId}, #{hashValue}, #{isDeleted}) + + + + + + + + + UPDATE file_hash SET is_deleted = 1 WHERE instance_id = #{instanceId} + + \ No newline at end of file diff --git a/timeline-file-service/src/main/resources/com/timeline/file/dao/ImageInfoMapper.xml b/timeline-file-service/src/main/resources/com/timeline/file/dao/ImageInfoMapper.xml index b140f23..dc43549 100644 --- a/timeline-file-service/src/main/resources/com/timeline/file/dao/ImageInfoMapper.xml +++ b/timeline-file-service/src/main/resources/com/timeline/file/dao/ImageInfoMapper.xml @@ -18,6 +18,22 @@ + + + + + + + UPDATE image_info SET object_key = #{objectKey}, + user_id = #{userId}, + update_time = #{updateTime}, + is_deleted = #{isDeleted} + WHERE instance_id = #{instanceId} + diff --git a/timeline-story-service/src/main/java/com/timeline/story/controller/HealthController.java b/timeline-story-service/src/main/java/com/timeline/story/controller/HealthController.java index 8822646..e5de7cd 100644 --- a/timeline-story-service/src/main/java/com/timeline/story/controller/HealthController.java +++ b/timeline-story-service/src/main/java/com/timeline/story/controller/HealthController.java @@ -1,6 +1,6 @@ package com.timeline.story.controller; -import com.timeline.response.ResponseEntity; +import com.timeline.common.response.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; diff --git a/timeline-story-service/src/main/java/com/timeline/story/controller/StoryController.java b/timeline-story-service/src/main/java/com/timeline/story/controller/StoryController.java index 3a087c5..7553a18 100644 --- a/timeline-story-service/src/main/java/com/timeline/story/controller/StoryController.java +++ b/timeline-story-service/src/main/java/com/timeline/story/controller/StoryController.java @@ -1,6 +1,6 @@ package com.timeline.story.controller; -import com.timeline.response.ResponseEntity; +import com.timeline.common.response.ResponseEntity; import com.timeline.story.entity.Story; import com.timeline.story.service.StoryService; import com.timeline.story.vo.StoryVo; diff --git a/timeline-story-service/src/main/java/com/timeline/story/controller/StoryItemController.java b/timeline-story-service/src/main/java/com/timeline/story/controller/StoryItemController.java index b9dad0d..de98e71 100644 --- a/timeline-story-service/src/main/java/com/timeline/story/controller/StoryItemController.java +++ b/timeline-story-service/src/main/java/com/timeline/story/controller/StoryItemController.java @@ -1,13 +1,12 @@ package com.timeline.story.controller; import com.alibaba.fastjson.JSONObject; -import com.timeline.response.ResponseEntity; +import com.timeline.common.response.ResponseEntity; import com.timeline.story.entity.StoryItem; import com.timeline.story.service.StoryItemService; import com.timeline.story.vo.StoryItemVo; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; diff --git a/timeline-story-service/src/main/java/com/timeline/story/dao/CommonRelationMapper.java b/timeline-story-service/src/main/java/com/timeline/story/dao/CommonRelationMapper.java index b98933c..cfeae5f 100644 --- a/timeline-story-service/src/main/java/com/timeline/story/dao/CommonRelationMapper.java +++ b/timeline-story-service/src/main/java/com/timeline/story/dao/CommonRelationMapper.java @@ -1,6 +1,6 @@ package com.timeline.story.dao; -import com.timeline.dto.CommonRelationDTO; +import com.timeline.common.dto.CommonRelationDTO; import org.apache.ibatis.annotations.Mapper; import java.util.List; diff --git a/timeline-story-service/src/main/java/com/timeline/story/entity/Story.java b/timeline-story-service/src/main/java/com/timeline/story/entity/Story.java index 00dd1c7..50ba5d9 100644 --- a/timeline-story-service/src/main/java/com/timeline/story/entity/Story.java +++ b/timeline-story-service/src/main/java/com/timeline/story/entity/Story.java @@ -18,4 +18,5 @@ public class Story { private Integer isDelete; private String ownerId; private String status; + private String logo; } diff --git a/timeline-story-service/src/main/java/com/timeline/story/feign/FileServiceClient.java b/timeline-story-service/src/main/java/com/timeline/story/feign/FileServiceClient.java index bf7d356..b23cdd1 100644 --- a/timeline-story-service/src/main/java/com/timeline/story/feign/FileServiceClient.java +++ b/timeline-story-service/src/main/java/com/timeline/story/feign/FileServiceClient.java @@ -1,20 +1,19 @@ package com.timeline.story.feign; -import com.timeline.response.ResponseEntity; +import com.timeline.common.response.ResponseEntity; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.core.io.InputStreamResource; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; -import java.io.InputStream; import java.util.List; @FeignClient(name = "timeline.file", url = "${file.service.url}") public interface FileServiceClient { - @PostMapping(value = "/upload-cover", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) - ResponseEntity uploadCover(@RequestPart("cover") MultipartFile cover); + @PostMapping(value = "/upload-image", consumes = MediaType.MULTIPART_FORM_DATA_VALUE) + ResponseEntity uploadCover(@RequestPart("image") MultipartFile image); @GetMapping("/download/cover/{coverKey}") InputStreamResource downloadCover(@PathVariable String coverKey); diff --git a/timeline-story-service/src/main/java/com/timeline/story/service/impl/StoryItemServiceImpl.java b/timeline-story-service/src/main/java/com/timeline/story/service/impl/StoryItemServiceImpl.java index 099e77c..22ab38f 100644 --- a/timeline-story-service/src/main/java/com/timeline/story/service/impl/StoryItemServiceImpl.java +++ b/timeline-story-service/src/main/java/com/timeline/story/service/impl/StoryItemServiceImpl.java @@ -1,18 +1,18 @@ package com.timeline.story.service.impl; -import com.timeline.constants.CommonConstants; +import com.timeline.common.constants.CommonConstants; import com.timeline.story.dao.CommonRelationMapper; -import com.timeline.dto.CommonRelationDTO; -import com.timeline.exception.CustomException; -import com.timeline.response.ResponseEntity; -import com.timeline.response.ResponseEnum; +import com.timeline.common.dto.CommonRelationDTO; +import com.timeline.common.exception.CustomException; +import com.timeline.common.response.ResponseEntity; +import com.timeline.common.response.ResponseEnum; import com.timeline.story.dao.StoryItemMapper; import com.timeline.story.entity.StoryItem; import com.timeline.story.feign.FileServiceClient; import com.timeline.story.service.StoryItemService; import com.timeline.story.vo.StoryItemVo; import com.timeline.story.vo.StoryItemWithCoverVo; -import com.timeline.utils.IdUtils; +import com.timeline.common.utils.IdUtils; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.io.InputStreamResource; diff --git a/timeline-story-service/src/main/java/com/timeline/story/service/impl/StoryServiceImpl.java b/timeline-story-service/src/main/java/com/timeline/story/service/impl/StoryServiceImpl.java index 1aeda32..edb9d05 100644 --- a/timeline-story-service/src/main/java/com/timeline/story/service/impl/StoryServiceImpl.java +++ b/timeline-story-service/src/main/java/com/timeline/story/service/impl/StoryServiceImpl.java @@ -1,12 +1,12 @@ package com.timeline.story.service.impl; -import com.timeline.exception.CustomException; -import com.timeline.response.ResponseEnum; +import com.timeline.common.exception.CustomException; +import com.timeline.common.response.ResponseEnum; import com.timeline.story.entity.Story; import com.timeline.story.dao.StoryMapper; import com.timeline.story.service.StoryService; import com.timeline.story.vo.StoryVo; -import com.timeline.utils.IdUtils; +import com.timeline.common.utils.IdUtils; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -32,6 +32,7 @@ public class StoryServiceImpl implements StoryService { story.setStatus(storyVo.getStatus()); story.setCreateTime(LocalDateTime.now()); story.setUpdateTime(LocalDateTime.now()); + story.setLogo(storyVo.getLogo()); story.setIsDelete(0); storyMapper.insert(story); } catch (Exception e) { @@ -52,6 +53,7 @@ public class StoryServiceImpl implements StoryService { story.setDescription(storyVo.getDescription()); story.setStatus(storyVo.getStatus()); story.setUpdateTime(LocalDateTime.now()); + story.setLogo(storyVo.getLogo()); storyMapper.update(story); } diff --git a/timeline-story-service/src/main/java/com/timeline/story/vo/StoryVo.java b/timeline-story-service/src/main/java/com/timeline/story/vo/StoryVo.java index d4d193e..59cda76 100644 --- a/timeline-story-service/src/main/java/com/timeline/story/vo/StoryVo.java +++ b/timeline-story-service/src/main/java/com/timeline/story/vo/StoryVo.java @@ -10,4 +10,5 @@ public class StoryVo { private String title; private String description; private String status; + private String logo; } diff --git a/timeline-story-service/src/main/resources/com/timeline/story/dao/StoryMapper.xml b/timeline-story-service/src/main/resources/com/timeline/story/dao/StoryMapper.xml index b1cf8b1..14b0680 100644 --- a/timeline-story-service/src/main/resources/com/timeline/story/dao/StoryMapper.xml +++ b/timeline-story-service/src/main/resources/com/timeline/story/dao/StoryMapper.xml @@ -5,8 +5,8 @@ - INSERT INTO story (instance_id, title, description, owner_id, status) - VALUES (#{instanceId}, #{title}, #{description}, #{ownerId}, #{status}) + INSERT INTO story (instance_id, title, description, owner_id, status, logo) + VALUES (#{instanceId}, #{title}, #{description}, #{ownerId}, #{status}, #{logo}) @@ -15,7 +15,8 @@ description = #{description}, update_id = #{updateId}, status = #{status}, - update_time = NOW() + update_time = NOW(), + logo = #{logo} WHERE instance_id = #{instanceId}