diff --git a/src/main/java/com/huangge1199/picture/controller/PictureController.java b/src/main/java/com/huangge1199/picture/controller/PictureController.java new file mode 100644 index 0000000..19059d0 --- /dev/null +++ b/src/main/java/com/huangge1199/picture/controller/PictureController.java @@ -0,0 +1,50 @@ +package com.huangge1199.picture.controller; + +import com.huangge1199.picture.annotation.AuthCheck; +import com.huangge1199.picture.common.R; +import com.huangge1199.picture.constant.UserConstant; +import com.huangge1199.picture.model.dto.picture.PictureUploadRequest; +import com.huangge1199.picture.model.entity.User; +import com.huangge1199.picture.model.vo.PictureVO; +import com.huangge1199.picture.service.PictureService; +import com.huangge1199.picture.service.UserService; +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 javax.annotation.Resource; +import javax.servlet.http.HttpServletRequest; + +/** + * 图片 + * + * @author huangge1199 + * @since 2025/7/26 14:36:52 + */ +@RestController +@RequestMapping("/pic") +public class PictureController { + + @Resource + private UserService userService; + + @Resource + private PictureService pictureService; + + /** + * 上传图片(可重新上传) + */ + @PostMapping("/upload") + @AuthCheck(mustRole = UserConstant.ADMIN_ROLE) + public R uploadPicture( + @RequestPart("file") MultipartFile multipartFile, + PictureUploadRequest pictureUploadRequest, + HttpServletRequest request) throws Exception { + User loginUser = userService.getLoginUser(request); + PictureVO pictureVO = pictureService.uploadPicture(multipartFile, pictureUploadRequest, loginUser); + return R.ok(pictureVO); + } + +} diff --git a/src/main/java/com/huangge1199/picture/mapper/PictureMapper.java b/src/main/java/com/huangge1199/picture/mapper/PictureMapper.java new file mode 100644 index 0000000..9561a62 --- /dev/null +++ b/src/main/java/com/huangge1199/picture/mapper/PictureMapper.java @@ -0,0 +1,18 @@ +package com.huangge1199.picture.mapper; + +import com.huangge1199.picture.model.Picture; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; + +/** +* @author hyy +* @description 针对表【picture(图片)】的数据库操作Mapper +* @createDate 2025-07-26 11:04:44 +* @Entity com.huangge1199.picture.model.Picture +*/ +public interface PictureMapper extends BaseMapper { + +} + + + + diff --git a/src/main/java/com/huangge1199/picture/model/Picture.java b/src/main/java/com/huangge1199/picture/model/Picture.java new file mode 100644 index 0000000..d63c083 --- /dev/null +++ b/src/main/java/com/huangge1199/picture/model/Picture.java @@ -0,0 +1,97 @@ +package com.huangge1199.picture.model; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import java.util.Date; +import lombok.Data; + +/** + * 图片 + * @author hyy + * @TableName picture + */ +@TableName(value ="picture") +@Data +public class Picture { + /** + * id + */ + @TableId(type = IdType.AUTO) + private Long id; + + /** + * 图片 url + */ + private String url; + + /** + * 图片名称 + */ + private String name; + + /** + * 简介 + */ + private String introduction; + + /** + * 分类 + */ + private String category; + + /** + * 标签(JSON 数组) + */ + private String tags; + + /** + * 图片体积 + */ + private Long picSize; + + /** + * 图片宽度 + */ + private Integer picWidth; + + /** + * 图片高度 + */ + private Integer picHeight; + + /** + * 图片宽高比例 + */ + private Double picScale; + + /** + * 图片格式 + */ + private String picFormat; + + /** + * 创建用户 id + */ + private Long userId; + + /** + * 创建时间 + */ + private Date createTime; + + /** + * 编辑时间 + */ + private Date editTime; + + /** + * 更新时间 + */ + private Date updateTime; + + /** + * 是否删除 + */ + private Integer isDelete; +} \ No newline at end of file diff --git a/src/main/java/com/huangge1199/picture/model/dto/file/UploadPictureResult.java b/src/main/java/com/huangge1199/picture/model/dto/file/UploadPictureResult.java new file mode 100644 index 0000000..ec820ad --- /dev/null +++ b/src/main/java/com/huangge1199/picture/model/dto/file/UploadPictureResult.java @@ -0,0 +1,57 @@ +package com.huangge1199.picture.model.dto.file; +import lombok.Data; + +/** + * UploadPictureResult + * + * @author huangge1199 + * @since 2025/7/26 13:24:59 + */ +@Data +public class UploadPictureResult { + + /** + * 图片地址 + */ + private String url; + + /** + * 缩略图 url + */ + private String thumbnailUrl; + + /** + * 图片名称 + */ + private String picName; + + /** + * 文件体积 + */ + private Long picSize; + + /** + * 图片宽度 + */ + private int picWidth; + + /** + * 图片高度 + */ + private int picHeight; + + /** + * 图片宽高比 + */ + private Double picScale; + + /** + * 图片格式 + */ + private String picFormat; + + /** + * 图片主色调 + */ + private String picColor; +} diff --git a/src/main/java/com/huangge1199/picture/model/dto/picture/PictureUpdateRequest.java b/src/main/java/com/huangge1199/picture/model/dto/picture/PictureUpdateRequest.java new file mode 100644 index 0000000..e8fa3f9 --- /dev/null +++ b/src/main/java/com/huangge1199/picture/model/dto/picture/PictureUpdateRequest.java @@ -0,0 +1,22 @@ +package com.huangge1199.picture.model.dto.picture; + +import lombok.Data; + +import java.io.Serializable; + +/** + * PictureUpdateRequest + * + * @author huangge1199 + * @since 2025/7/26 11:18:05 + */ +@Data +public class PictureUpdateRequest implements Serializable { + + /** + * id + */ + private Long id; + + private static final long serialVersionUID = 1L; +} diff --git a/src/main/java/com/huangge1199/picture/model/dto/picture/PictureUploadByBatchRequest.java b/src/main/java/com/huangge1199/picture/model/dto/picture/PictureUploadByBatchRequest.java new file mode 100644 index 0000000..5c83663 --- /dev/null +++ b/src/main/java/com/huangge1199/picture/model/dto/picture/PictureUploadByBatchRequest.java @@ -0,0 +1,32 @@ +package com.huangge1199.picture.model.dto.picture; + +import lombok.Data; + +import java.io.Serializable; + +/** + * PictureUploadByBatchRequest + * + * @author huangge1199 + * @since 2025/7/26 13:36:20 + */ +@Data +public class PictureUploadByBatchRequest implements Serializable { + + /** + * 搜索词 + */ + private String searchText; + + /** + * 抓取数量 + */ + private Integer count = 10; + + /** + * 图片名称前缀 + */ + private String namePrefix; + + private static final long serialVersionUID = 1L; +} diff --git a/src/main/java/com/huangge1199/picture/model/dto/picture/PictureUploadRequest.java b/src/main/java/com/huangge1199/picture/model/dto/picture/PictureUploadRequest.java new file mode 100644 index 0000000..342f35a --- /dev/null +++ b/src/main/java/com/huangge1199/picture/model/dto/picture/PictureUploadRequest.java @@ -0,0 +1,32 @@ +package com.huangge1199.picture.model.dto.picture; + +import lombok.Data; + +import java.io.Serializable; + +/** + * PictureUploadRequest + * + * @author huangge1199 + * @since 2025/7/26 13:37:11 + */ +@Data +public class PictureUploadRequest implements Serializable { + + /** + * 图片 id(用于修改) + */ + private Long id; + + /** + * 文件地址 + */ + private String fileUrl; + + /** + * 图片名称 + */ + private String picName; + + private static final long serialVersionUID = 1L; +} diff --git a/src/main/java/com/huangge1199/picture/model/vo/PictureVO.java b/src/main/java/com/huangge1199/picture/model/vo/PictureVO.java new file mode 100644 index 0000000..2fb3910 --- /dev/null +++ b/src/main/java/com/huangge1199/picture/model/vo/PictureVO.java @@ -0,0 +1,151 @@ +package com.huangge1199.picture.model.vo; + +import cn.hutool.json.JSONUtil; +import com.huangge1199.picture.model.Picture; +import lombok.Data; +import org.springframework.beans.BeanUtils; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +/** + * PictureVO + * + * @author huangge1199 + * @since 2025/7/26 13:23:02 + */ +@Data +public class PictureVO implements Serializable { + + /** + * id + */ + private Long id; + + /** + * 图片 url + */ + private String url; + + /** + * 缩略图 url + */ + private String thumbnailUrl; + + /** + * 图片名称 + */ + private String name; + + /** + * 简介 + */ + private String introduction; + + /** + * 标签 + */ + private List tags; + + /** + * 分类 + */ + private String category; + + /** + * 文件体积 + */ + private Long picSize; + + /** + * 图片宽度 + */ + private Integer picWidth; + + /** + * 图片高度 + */ + private Integer picHeight; + + /** + * 图片比例 + */ + private Double picScale; + + /** + * 图片格式 + */ + private String picFormat; + + /** + * 图片主色调 + */ + private String picColor; + + /** + * 用户 id + */ + private Long userId; + + /** + * 空间 id + */ + private Long spaceId; + + /** + * 创建时间 + */ + private Date createTime; + + /** + * 编辑时间 + */ + private Date editTime; + + /** + * 更新时间 + */ + private Date updateTime; + + /** + * 创建用户信息 + */ + private UserVO user; + + /** + * 权限列表 + */ + private List permissionList = new ArrayList<>(); + + private static final long serialVersionUID = 1L; + + /** + * 封装类转对象 + */ + public static Picture voToObj(PictureVO pictureVO) { + if (pictureVO == null) { + return null; + } + Picture picture = new Picture(); + BeanUtils.copyProperties(pictureVO, picture); + // 类型不同,需要转换 + picture.setTags(JSONUtil.toJsonStr(pictureVO.getTags())); + return picture; + } + + /** + * 对象转封装类 + */ + public static PictureVO objToVo(Picture picture) { + if (picture == null) { + return null; + } + PictureVO pictureVO = new PictureVO(); + BeanUtils.copyProperties(picture, pictureVO); + // 类型不同,需要转换 + pictureVO.setTags(JSONUtil.toList(picture.getTags(), String.class)); + return pictureVO; + } +} \ No newline at end of file diff --git a/src/main/java/com/huangge1199/picture/service/PictureService.java b/src/main/java/com/huangge1199/picture/service/PictureService.java new file mode 100644 index 0000000..5c1395c --- /dev/null +++ b/src/main/java/com/huangge1199/picture/service/PictureService.java @@ -0,0 +1,30 @@ +package com.huangge1199.picture.service; + +import com.huangge1199.picture.model.Picture; +import com.baomidou.mybatisplus.extension.service.IService; +import com.huangge1199.picture.model.dto.picture.PictureUploadRequest; +import com.huangge1199.picture.model.entity.User; +import com.huangge1199.picture.model.vo.PictureVO; +import org.springframework.web.multipart.MultipartFile; + +import java.io.IOException; + +/** + * @author hyy + * @description 针对表【picture(图片)】的数据库操作Service + * @createDate 2025-07-26 11:04:44 + */ +public interface PictureService extends IService { + /** + * 上传图片 + * + * @param multipartFile + * @param pictureUploadRequest + * @param loginUser + * @return + */ + PictureVO uploadPicture(MultipartFile multipartFile, + PictureUploadRequest pictureUploadRequest, + User loginUser) throws Exception; + +} diff --git a/src/main/java/com/huangge1199/picture/service/PictureSevice.java b/src/main/java/com/huangge1199/picture/service/PictureSevice.java new file mode 100644 index 0000000..2c36206 --- /dev/null +++ b/src/main/java/com/huangge1199/picture/service/PictureSevice.java @@ -0,0 +1,27 @@ +package com.huangge1199.picture.service; + +import com.huangge1199.picture.model.dto.picture.PictureUploadRequest; +import com.huangge1199.picture.model.entity.User; +import com.huangge1199.picture.model.vo.PictureVO; +import org.springframework.web.multipart.MultipartFile; + +/** + * PictureSevice + * + * @author huangge1199 + * @since 2025/7/26 13:34:02 + */ +public interface PictureSevice { + /** + * 上传图片 + * + * @param multipartFile + * @param pictureUploadRequest + * @param loginUser + * @return + */ + PictureVO uploadPicture(MultipartFile multipartFile, + PictureUploadRequest pictureUploadRequest, + User loginUser); + +} diff --git a/src/main/java/com/huangge1199/picture/service/impl/PictureServiceImpl.java b/src/main/java/com/huangge1199/picture/service/impl/PictureServiceImpl.java new file mode 100644 index 0000000..8a61555 --- /dev/null +++ b/src/main/java/com/huangge1199/picture/service/impl/PictureServiceImpl.java @@ -0,0 +1,90 @@ +package com.huangge1199.picture.service.impl; + +import cn.hutool.core.io.FileUtil; +import cn.hutool.core.util.NumberUtil; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.huangge1199.picture.exception.ErrorCode; +import com.huangge1199.picture.exception.ThrowUtils; +import com.huangge1199.picture.model.Picture; +import com.huangge1199.picture.model.dto.file.UploadPictureResult; +import com.huangge1199.picture.model.dto.picture.PictureUploadRequest; +import com.huangge1199.picture.model.entity.User; +import com.huangge1199.picture.model.vo.PictureVO; +import com.huangge1199.picture.service.PictureService; +import com.huangge1199.picture.mapper.PictureMapper; +import com.huangge1199.picture.utils.MinioUtil; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; + +import javax.annotation.Resource; +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.IOException; +import java.util.Date; + +/** + * @author hyy + * @description 针对表【picture(图片)】的数据库操作Service实现 + * @createDate 2025-07-26 11:04:44 + */ +@Service +public class PictureServiceImpl extends ServiceImpl + implements PictureService { + + @Resource + private MinioUtil minioUtil; + + @Override + public PictureVO uploadPicture(MultipartFile multipartFile, PictureUploadRequest pictureUploadRequest, User loginUser) throws Exception { + ThrowUtils.throwIf(loginUser == null, ErrorCode.NO_AUTH_ERROR); + // 用于判断是新增还是更新图片 + Long pictureId = null; + if (pictureUploadRequest != null) { + pictureId = pictureUploadRequest.getId(); + } + // 如果是更新图片,需要校验图片是否存在 + if (pictureId != null) { + boolean exists = this.lambdaQuery() + .eq(Picture::getId, pictureId) + .exists(); + ThrowUtils.throwIf(!exists, ErrorCode.NOT_FOUND_ERROR, "图片不存在"); + } + // 上传图片 + // 生成唯一文件名 + String originalFilename = multipartFile.getOriginalFilename(); + String fileExtension = originalFilename.substring(originalFilename.lastIndexOf(".")); + + String url = minioUtil.upload(multipartFile.getInputStream(), fileExtension, multipartFile.getContentType()); + + String fileName = url.substring(url.lastIndexOf("/") + 1, url.lastIndexOf(".")); + + // 构造要入库的图片信息 + Picture picture = new Picture(); + picture.setUrl(url); + picture.setName(fileName); + BufferedImage image = ImageIO.read(multipartFile.getInputStream()); + int width = image.getWidth(); + int height = image.getHeight(); + double scale = NumberUtil.round(width * 1.0 / height, 2).doubleValue(); + picture.setPicSize(multipartFile.getSize()); + picture.setPicWidth(width); + picture.setPicHeight(height); + picture.setPicScale(scale); + picture.setPicFormat(url.substring(url.lastIndexOf(".") + 1)); + picture.setUserId(loginUser.getId()); + // 如果 pictureId 不为空,表示更新,否则是新增 + if (pictureId != null) { + // 如果是更新,需要补充 id 和编辑时间 + picture.setId(pictureId); + picture.setEditTime(new Date()); + } + boolean result = this.saveOrUpdate(picture); + ThrowUtils.throwIf(!result, ErrorCode.OPERATION_ERROR, "图片上传失败"); + return PictureVO.objToVo(picture); + } + +} + + + + diff --git a/src/main/java/com/huangge1199/picture/utils/FileUtil.java b/src/main/java/com/huangge1199/picture/utils/FileUtil.java new file mode 100644 index 0000000..e0e4e46 --- /dev/null +++ b/src/main/java/com/huangge1199/picture/utils/FileUtil.java @@ -0,0 +1,30 @@ +package com.huangge1199.picture.utils; + +import com.huangge1199.picture.exception.ErrorCode; +import com.huangge1199.picture.exception.ThrowUtils; +import com.huangge1199.picture.model.dto.file.UploadPictureResult; +import org.springframework.stereotype.Component; +import org.springframework.web.multipart.MultipartFile; + +import javax.annotation.Resource; +import java.io.InputStream; + +/** + * FileUtil + * + * @author huangge1199 + * @since 2025/7/26 13:28:09 + */ +@Component +public class FileUtil { + + @Resource + private MinioUtil minioUtil; + + public void validPicture(MultipartFile multipartFile) throws Exception { + ThrowUtils.throwIf(multipartFile == null, ErrorCode.PARAMS_ERROR, "文件不能为空!"); + long fileSize = multipartFile.getSize(); + final long ONE_M = 1024 * 1024L; + ThrowUtils.throwIf(fileSize > 2 * ONE_M, ErrorCode.PARAMS_ERROR, "文件大小不能超过2M"); + } +} diff --git a/src/main/java/com/huangge1199/picture/utils/MinioUtil.java b/src/main/java/com/huangge1199/picture/utils/MinioUtil.java index 9262a97..5f53503 100644 --- a/src/main/java/com/huangge1199/picture/utils/MinioUtil.java +++ b/src/main/java/com/huangge1199/picture/utils/MinioUtil.java @@ -2,6 +2,7 @@ package com.huangge1199.picture.utils; import io.minio.*; import lombok.extern.slf4j.Slf4j; +import lombok.val; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 5b11252..ee61019 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -13,6 +13,9 @@ spring: password: 数据库密码 profiles: active: local + servlet: + multipart: + max-file-size: 10MB mybatis-plus: configuration: map-underscore-to-camel-case: false diff --git a/src/main/resources/com/huangge1199/picture/mapper/PictureMapper.xml b/src/main/resources/com/huangge1199/picture/mapper/PictureMapper.xml new file mode 100644 index 0000000..11d3a70 --- /dev/null +++ b/src/main/resources/com/huangge1199/picture/mapper/PictureMapper.xml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + + + + + id,url,name,introduction,category,tags, + picSize,picWidth,picHeight,picScale,picFormat, + userId,createTime,editTime,updateTime,isDelete + +