From e8455a3a588bc8ebba2edd01bccbd86236909ef1 Mon Sep 17 00:00:00 2001 From: none Date: Wed, 8 Mar 2023 15:56:44 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E5=96=84minio=E4=B8=8A=E4=BC=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../playedu/api/constant/BackendConstant.java | 19 ++-- .../backend/ResourceController.java | 13 ++- .../controller/backend/UploadController.java | 99 +++++++++++-------- .../java/xyz/playedu/api/domain/Resource.java | 47 ++++++--- .../playedu/api/mapper/ResourceMapper.java | 2 +- .../api/request/backend/ResourceRequest.java | 2 + .../backend/UploadVideoMergeRequest.java | 40 ++++++++ .../xyz/playedu/api/service/MinioService.java | 2 + .../api/service/ResourceCategoryService.java | 2 + .../playedu/api/service/ResourceService.java | 4 + .../playedu/api/service/UploadService.java | 15 +++ .../api/service/impl/MinioServiceImpl.java | 21 +++- .../impl/ResourceCategoryServiceImpl.java | 5 + .../api/service/impl/ResourceServiceImpl.java | 21 +++- .../api/service/impl/UploadServiceImpl.java | 91 +++++++++++++++++ src/main/resources/mapper/ResourceMapper.xml | 5 +- 16 files changed, 321 insertions(+), 67 deletions(-) create mode 100644 src/main/java/xyz/playedu/api/request/backend/UploadVideoMergeRequest.java create mode 100644 src/main/java/xyz/playedu/api/service/UploadService.java create mode 100644 src/main/java/xyz/playedu/api/service/impl/UploadServiceImpl.java diff --git a/src/main/java/xyz/playedu/api/constant/BackendConstant.java b/src/main/java/xyz/playedu/api/constant/BackendConstant.java index c3c4d2e..7d09477 100644 --- a/src/main/java/xyz/playedu/api/constant/BackendConstant.java +++ b/src/main/java/xyz/playedu/api/constant/BackendConstant.java @@ -38,19 +38,26 @@ public class BackendConstant { put("ppt", RESOURCE_TYPE_PPT); put("pptx", RESOURCE_TYPE_PPT); }}; + public final static HashMap RESOURCE_TYPE_2_DIR = new HashMap<>() {{ + put(RESOURCE_TYPE_VIDEO, UPLOAD_VIDEO_DIR); + put(RESOURCE_TYPE_IMAGE, UPLOAD_IMAGE_DIR); + put(RESOURCE_TYPE_PDF, UPLOAD_PDF_DIR); + put(RESOURCE_TYPE_WORD, UPLOAD_WORD_DIR); + put(RESOURCE_TYPE_PPT, UPLOAD_PPT_DIR); + }}; - public final static String[] RESOURCE_DISK_WHITELIST = {"minio"}; + public final static String STORAGE_DRIVER_MINIO = "minio"; + + public final static String[] RESOURCE_DISK_WHITELIST = {STORAGE_DRIVER_MINIO}; public final static String[] COURSE_HOUR_TYPE_WHITELIST = {"VIDEO"}; public final static String[] COURSE_HOUR_TYPE_WHITELIST_TEXT = {"视频"}; - // 图片上传相关配置 - public final static String[] UPLOAD_IMAGE_EXT_WL = {"png", "jpg", "jpeg", "gif"}; - public final static String[] UPLOAD_IMAGE_CONTENT_TYPE_WL = {"image/png", "image/jpg", "image/jpeg", "image/gif"}; public final static String UPLOAD_IMAGE_DIR = "images/"; - - // 视频上传配置 public final static String UPLOAD_VIDEO_DIR = "videos/"; + public final static String UPLOAD_PDF_DIR = "pdf/"; + public final static String UPLOAD_WORD_DIR = "word/"; + public final static String UPLOAD_PPT_DIR = "word/"; public final static String PRIVACY_FIELD_TYPE_EMAIL = "email"; public final static String PRIVACY_FIELD_TYPE_PHONE = "phone"; diff --git a/src/main/java/xyz/playedu/api/controller/backend/ResourceController.java b/src/main/java/xyz/playedu/api/controller/backend/ResourceController.java index adc4550..93cf61a 100644 --- a/src/main/java/xyz/playedu/api/controller/backend/ResourceController.java +++ b/src/main/java/xyz/playedu/api/controller/backend/ResourceController.java @@ -116,11 +116,20 @@ public class ResourceController { return JsonResponse.error("duration参数必须存在且大于0"); } if (poster == null || poster.trim().length() == 0) { - return JsonResponse.error("视频封面为空"); + return JsonResponse.error("poster参数值不能为空"); } } - Resource res = resourceService.create(req.getCategoryId(), type, req.getName(), extension, req.getSize(), disk, req.getFileId(), req.getPath(), req.getUrl()); + Resource res = resourceService.create( + req.getCategoryId(), + type, req.getName(), + extension, + req.getSize(), + disk, + req.getFileId(), + req.getPath(), + req.getUrl() + ); if (isVideoType) { resourceVideoService.create(res.getId(), duration, poster); diff --git a/src/main/java/xyz/playedu/api/controller/backend/UploadController.java b/src/main/java/xyz/playedu/api/controller/backend/UploadController.java index 996ae19..07bed25 100644 --- a/src/main/java/xyz/playedu/api/controller/backend/UploadController.java +++ b/src/main/java/xyz/playedu/api/controller/backend/UploadController.java @@ -3,17 +3,20 @@ package xyz.playedu.api.controller.backend; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.MapUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import xyz.playedu.api.constant.BackendConstant; import xyz.playedu.api.domain.Resource; +import xyz.playedu.api.exception.ServiceException; +import xyz.playedu.api.request.backend.UploadVideoMergeRequest; import xyz.playedu.api.service.MinioService; import xyz.playedu.api.service.ResourceCategoryService; import xyz.playedu.api.service.ResourceService; +import xyz.playedu.api.service.UploadService; import xyz.playedu.api.types.JsonResponse; import xyz.playedu.api.util.HelperUtil; -import java.util.Arrays; import java.util.HashMap; /** @@ -24,74 +27,49 @@ import java.util.HashMap; @Slf4j @RequestMapping("/backend/v1/upload") public class UploadController { - - @Autowired - private ResourceService resourceService; - @Autowired private ResourceCategoryService resourceCategoryService; @Autowired private MinioService minioService; - @PostMapping("/image") - public JsonResponse image(@RequestParam HashMap params, MultipartFile file) { - if (file == null || file.isEmpty() || file.getOriginalFilename() == null) { - return JsonResponse.error("请上传文件"); - } + @Autowired + private UploadService uploadService; - String contentType = file.getContentType(); - if (contentType == null || !Arrays.asList(BackendConstant.UPLOAD_IMAGE_CONTENT_TYPE_WL).contains(contentType)) { - return JsonResponse.error("格式不支持"); - } + @Autowired + private ResourceService resourceService; + @PostMapping("/file") + public JsonResponse image(@RequestParam HashMap params, MultipartFile file) throws ServiceException { Integer cid = MapUtils.getInteger(params, "category_id"); - if (cid != null && !cid.equals(0) && resourceCategoryService.getById(cid) == null) { - return JsonResponse.error("分类不存在"); - } - - String filename = file.getOriginalFilename(); - String ext = HelperUtil.fileExt(filename); - if (!Arrays.asList(BackendConstant.UPLOAD_IMAGE_EXT_WL).contains(ext)) { - return JsonResponse.error("格式不支持"); - } - - String oldFilename = filename.replaceAll("." + ext, ""); - String newFilename = HelperUtil.randomString(32) + "." + ext; - String savePath = BackendConstant.UPLOAD_IMAGE_DIR + newFilename; - - // 保存文件 - String url = minioService.saveFile(file, savePath, contentType); - // 上传记录 - Resource res = resourceService.create(cid, BackendConstant.RESOURCE_TYPE_IMAGE, oldFilename, ext, file.getSize(), "minio", "", savePath, url); - + Resource res = uploadService.storeMinio(file, cid); return JsonResponse.data(res); } - @GetMapping("/minio-upload-id") + @GetMapping("/minio/upload-id") public JsonResponse minioUploadId(@RequestParam HashMap params) { String extension = MapUtils.getString(params, "extension"); if (extension == null || extension.trim().length() == 0) { return JsonResponse.error("extension参数为空"); } - String contentType = BackendConstant.RESOURCE_EXT_2_CONTENT_TYPE.get(extension.toLowerCase()); - if (contentType == null) { - return JsonResponse.error("该格式不支持上传"); + String type = BackendConstant.RESOURCE_EXT_2_TYPE.get(extension.toLowerCase()); + if (type == null) { + return JsonResponse.error("该格式文件不支持上传"); } String filename = HelperUtil.randomString(32) + "." + extension;//文件名 - String path = BackendConstant.UPLOAD_VIDEO_DIR + filename;//存储路径 + String path = BackendConstant.RESOURCE_TYPE_2_DIR.get(type) + filename;//存储路径 String uploadId = minioService.uploadId(path); HashMap data = new HashMap<>(); - data.put("resource_type", BackendConstant.RESOURCE_EXT_2_TYPE.get(extension.toLowerCase())); + data.put("resource_type", type); data.put("upload_id", uploadId); data.put("filename", path); return JsonResponse.data(data); } - @GetMapping("/minio-pre-sign-url") + @GetMapping("/minio/pre-sign-url") public JsonResponse minioPreSignUrl(@RequestParam HashMap params) { String uploadId = MapUtils.getString(params, "upload_id"); Integer partNumber = MapUtils.getInteger(params, "part_number"); @@ -105,7 +83,46 @@ public class UploadController { return JsonResponse.data(data); } - @GetMapping("/minio-merge") + @PostMapping("/minio/merge-video") + public JsonResponse minioMergeVideo(@RequestBody @Validated UploadVideoMergeRequest req) throws ServiceException { + Integer cid = req.getCategoryId(); + String type = BackendConstant.RESOURCE_EXT_2_TYPE.get(req.getExtension()); + if (type == null) { + return JsonResponse.error("当前格式不支持上传"); + } + if (cid != null && resourceCategoryService.find(cid, type) == null) { + return JsonResponse.error("资源分类不存在"); + } + + // 合并视频文件 + String url = minioService.merge(req.getFilename(), req.getUploadId()); + + // 视频素材保存 + Resource videoResource = resourceService.create( + cid, + type, + req.getOriginalFilename(), + req.getExtension(), + req.getSize(), + BackendConstant.STORAGE_DRIVER_MINIO, + "", + req.getFilename(), + url + ); + // 视频封面素材保存 + Resource posterResource = uploadService.storeBase64Image(req.getPoster(), 0); + // 视频的封面素材改为[隐藏 && 属于视频的子素材] + resourceService.changeParentId(posterResource.getId(), videoResource.getId()); + // 视频信息 + resourceService.storeResourceVideo(videoResource.getId(), req.getDuration(), posterResource.getUrl()); + + HashMap data = new HashMap<>(); + data.put("url", url); + + return JsonResponse.data(data); + } + + @GetMapping("/minio/merge") public JsonResponse minioMerge(@RequestParam HashMap params) { String filename = MapUtils.getString(params, "filename"); String uploadId = MapUtils.getString(params, "upload_id"); diff --git a/src/main/java/xyz/playedu/api/domain/Resource.java b/src/main/java/xyz/playedu/api/domain/Resource.java index cbf38aa..2dc3244 100644 --- a/src/main/java/xyz/playedu/api/domain/Resource.java +++ b/src/main/java/xyz/playedu/api/domain/Resource.java @@ -4,21 +4,22 @@ import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; + import java.io.Serializable; import java.util.Date; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; /** - * * @TableName resources */ -@TableName(value ="resources") +@TableName(value = "resources") @Data public class Resource implements Serializable { /** - * + * */ @TableId(type = IdType.AUTO) private Integer id; @@ -71,11 +72,23 @@ public class Resource implements Serializable { private String url; /** - * + * */ @JsonProperty("created_at") private Date createdAt; + /** + * 所属素材 + */ + @JsonProperty("parent_id") + private Integer parentId; + + /** + * 隐藏[0:否,1:是] + */ + @JsonIgnore + private Integer isHidden; + @TableField(exist = false) private static final long serialVersionUID = 1L; @@ -92,16 +105,18 @@ public class Resource implements Serializable { } Resource other = (Resource) that; return (this.getId() == null ? other.getId() == null : this.getId().equals(other.getId())) - && (this.getType() == null ? other.getType() == null : this.getType().equals(other.getType())) - && (this.getCategoryId() == null ? other.getCategoryId() == null : this.getCategoryId().equals(other.getCategoryId())) - && (this.getName() == null ? other.getName() == null : this.getName().equals(other.getName())) - && (this.getExtension() == null ? other.getExtension() == null : this.getExtension().equals(other.getExtension())) - && (this.getSize() == null ? other.getSize() == null : this.getSize().equals(other.getSize())) - && (this.getDisk() == null ? other.getDisk() == null : this.getDisk().equals(other.getDisk())) - && (this.getFileId() == null ? other.getFileId() == null : this.getFileId().equals(other.getFileId())) - && (this.getPath() == null ? other.getPath() == null : this.getPath().equals(other.getPath())) - && (this.getUrl() == null ? other.getUrl() == null : this.getUrl().equals(other.getUrl())) - && (this.getCreatedAt() == null ? other.getCreatedAt() == null : this.getCreatedAt().equals(other.getCreatedAt())); + && (this.getType() == null ? other.getType() == null : this.getType().equals(other.getType())) + && (this.getCategoryId() == null ? other.getCategoryId() == null : this.getCategoryId().equals(other.getCategoryId())) + && (this.getName() == null ? other.getName() == null : this.getName().equals(other.getName())) + && (this.getExtension() == null ? other.getExtension() == null : this.getExtension().equals(other.getExtension())) + && (this.getSize() == null ? other.getSize() == null : this.getSize().equals(other.getSize())) + && (this.getDisk() == null ? other.getDisk() == null : this.getDisk().equals(other.getDisk())) + && (this.getFileId() == null ? other.getFileId() == null : this.getFileId().equals(other.getFileId())) + && (this.getPath() == null ? other.getPath() == null : this.getPath().equals(other.getPath())) + && (this.getUrl() == null ? other.getUrl() == null : this.getUrl().equals(other.getUrl())) + && (this.getCreatedAt() == null ? other.getCreatedAt() == null : this.getCreatedAt().equals(other.getCreatedAt())) + && (this.getParentId() == null ? other.getParentId() == null : this.getParentId().equals(other.getParentId())) + && (this.getIsHidden() == null ? other.getIsHidden() == null : this.getIsHidden().equals(other.getIsHidden())); } @Override @@ -119,6 +134,8 @@ public class Resource implements Serializable { result = prime * result + ((getPath() == null) ? 0 : getPath().hashCode()); result = prime * result + ((getUrl() == null) ? 0 : getUrl().hashCode()); result = prime * result + ((getCreatedAt() == null) ? 0 : getCreatedAt().hashCode()); + result = prime * result + ((getParentId() == null) ? 0 : getParentId().hashCode()); + result = prime * result + ((getIsHidden() == null) ? 0 : getIsHidden().hashCode()); return result; } @@ -139,6 +156,8 @@ public class Resource implements Serializable { sb.append(", path=").append(path); sb.append(", url=").append(url); sb.append(", createdAt=").append(createdAt); + sb.append(", parentId=").append(parentId); + sb.append(", isHidden=").append(isHidden); sb.append(", serialVersionUID=").append(serialVersionUID); sb.append("]"); return sb.toString(); diff --git a/src/main/java/xyz/playedu/api/mapper/ResourceMapper.java b/src/main/java/xyz/playedu/api/mapper/ResourceMapper.java index 12f5d01..842976a 100644 --- a/src/main/java/xyz/playedu/api/mapper/ResourceMapper.java +++ b/src/main/java/xyz/playedu/api/mapper/ResourceMapper.java @@ -7,7 +7,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; /** * @author tengteng * @description 针对表【resources】的数据库操作Mapper -* @createDate 2023-03-06 10:06:57 +* @createDate 2023-03-08 13:43:00 * @Entity xyz.playedu.api.domain.Resource */ @Mapper diff --git a/src/main/java/xyz/playedu/api/request/backend/ResourceRequest.java b/src/main/java/xyz/playedu/api/request/backend/ResourceRequest.java index ac77855..cb9e0ce 100644 --- a/src/main/java/xyz/playedu/api/request/backend/ResourceRequest.java +++ b/src/main/java/xyz/playedu/api/request/backend/ResourceRequest.java @@ -49,4 +49,6 @@ public class ResourceRequest { private String poster; + private Integer parentId; + } diff --git a/src/main/java/xyz/playedu/api/request/backend/UploadVideoMergeRequest.java b/src/main/java/xyz/playedu/api/request/backend/UploadVideoMergeRequest.java new file mode 100644 index 0000000..e2009ec --- /dev/null +++ b/src/main/java/xyz/playedu/api/request/backend/UploadVideoMergeRequest.java @@ -0,0 +1,40 @@ +package xyz.playedu.api.request.backend; + +import com.fasterxml.jackson.annotation.JsonProperty; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +/** + * @Author 杭州白书科技有限公司 + * @create 2023/3/8 14:49 + */ +@Data +public class UploadVideoMergeRequest { + + @NotBlank(message = "请输入课程标题") + private String filename; + + @JsonProperty("upload_id") + @NotBlank(message = "请输入upload_id") + private String uploadId; + + @JsonProperty("original_filename") + @NotBlank(message = "请输入original_filename") + private String originalFilename; + + @NotNull(message = "请输入size") + private Long size; + + @NotNull(message = "请输入duration") + private Integer duration; + + @NotBlank(message = "请输入extension") + private String extension; + + private Integer categoryId; + + @NotNull(message = "请上传视频封面") + private String poster; + +} diff --git a/src/main/java/xyz/playedu/api/service/MinioService.java b/src/main/java/xyz/playedu/api/service/MinioService.java index 130eb1c..4e0842c 100644 --- a/src/main/java/xyz/playedu/api/service/MinioService.java +++ b/src/main/java/xyz/playedu/api/service/MinioService.java @@ -12,6 +12,8 @@ public interface MinioService { String saveFile(MultipartFile file, String savePath, String contentType); + String saveBytes(byte[] file, String savePath, String contentType); + String uploadId(String path); String chunkPreSignUrl(String filename, String partNumber, String uploadId); diff --git a/src/main/java/xyz/playedu/api/service/ResourceCategoryService.java b/src/main/java/xyz/playedu/api/service/ResourceCategoryService.java index 69077b3..a6920fb 100644 --- a/src/main/java/xyz/playedu/api/service/ResourceCategoryService.java +++ b/src/main/java/xyz/playedu/api/service/ResourceCategoryService.java @@ -19,6 +19,8 @@ public interface ResourceCategoryService extends IService { ResourceCategory findOrFail(Integer id) throws NotFoundException; + ResourceCategory find(Integer id, String type); + void update(ResourceCategory category, Integer sort, String name); } diff --git a/src/main/java/xyz/playedu/api/service/ResourceService.java b/src/main/java/xyz/playedu/api/service/ResourceService.java index 6e34ef8..ae6afde 100644 --- a/src/main/java/xyz/playedu/api/service/ResourceService.java +++ b/src/main/java/xyz/playedu/api/service/ResourceService.java @@ -19,4 +19,8 @@ public interface ResourceService extends IService { Resource findOrFail(Integer id) throws NotFoundException; + void changeParentId(Integer id, Integer parentId); + + void storeResourceVideo(Integer rid, Integer duration, String poster); + } diff --git a/src/main/java/xyz/playedu/api/service/UploadService.java b/src/main/java/xyz/playedu/api/service/UploadService.java new file mode 100644 index 0000000..07b9f98 --- /dev/null +++ b/src/main/java/xyz/playedu/api/service/UploadService.java @@ -0,0 +1,15 @@ +package xyz.playedu.api.service; + +import org.springframework.web.multipart.MultipartFile; +import xyz.playedu.api.domain.Resource; +import xyz.playedu.api.exception.ServiceException; + +/** + * @Author 杭州白书科技有限公司 + * @create 2023/3/8 14:02 + */ +public interface UploadService { + Resource storeMinio(MultipartFile file, Integer categoryId) throws ServiceException; + + Resource storeBase64Image(String content,Integer categoryId) throws ServiceException; +} diff --git a/src/main/java/xyz/playedu/api/service/impl/MinioServiceImpl.java b/src/main/java/xyz/playedu/api/service/impl/MinioServiceImpl.java index 524356a..4dae7a1 100644 --- a/src/main/java/xyz/playedu/api/service/impl/MinioServiceImpl.java +++ b/src/main/java/xyz/playedu/api/service/impl/MinioServiceImpl.java @@ -13,6 +13,8 @@ import xyz.playedu.api.config.MinioConfig; import xyz.playedu.api.service.MinioService; import xyz.playedu.api.vendor.PlayEduMinioClient; +import java.io.ByteArrayInputStream; +import java.io.InputStream; import java.util.HashMap; import java.util.Map; @@ -34,7 +36,7 @@ public class MinioServiceImpl implements MinioService { @Override public String url(String path) { - return c.getDomain() + c.getBucket() + path; + return c.getDomain() + c.getBucket() + "/" + path; } @Override @@ -85,4 +87,21 @@ public class MinioServiceImpl implements MinioService { public void removeByPath(String path) { client.removeObject(RemoveObjectArgs.builder().bucket(c.getBucket()).object(path).build()); } + + @Override + @SneakyThrows + public String saveBytes(byte[] file, String savePath, String contentType) { + InputStream inputStream = new ByteArrayInputStream(file); + + PutObjectArgs objectArgs = PutObjectArgs.builder() + .bucket(c.getBucket()) + .object(savePath) + .stream(inputStream, file.length, -1) + .contentType(contentType) + .build(); + + client.putObject(objectArgs); + + return url(savePath); + } } diff --git a/src/main/java/xyz/playedu/api/service/impl/ResourceCategoryServiceImpl.java b/src/main/java/xyz/playedu/api/service/impl/ResourceCategoryServiceImpl.java index 5ce9a59..f518235 100644 --- a/src/main/java/xyz/playedu/api/service/impl/ResourceCategoryServiceImpl.java +++ b/src/main/java/xyz/playedu/api/service/impl/ResourceCategoryServiceImpl.java @@ -53,6 +53,11 @@ public class ResourceCategoryServiceImpl extends ServiceImpl implements ResourceService { + @Autowired + private ResourceVideoService resourceVideoService; + @Override public PaginationResult paginate(int page, int size, ResourcePaginateFilter filter) { - QueryWrapper wrapper = query().getWrapper().eq("1", "1"); + QueryWrapper wrapper = query().getWrapper().eq("is_hidden", 0); if (filter.getName() != null) { wrapper.like("name", "%" + filter.getName() + "%"); @@ -93,6 +98,20 @@ public class ResourceServiceImpl extends ServiceImpl i } return resource; } + + @Override + public void changeParentId(Integer id, Integer parentId) { + Resource resource = new Resource(); + resource.setId(id); + resource.setParentId(parentId); + resource.setIsHidden(1); + updateById(resource); + } + + @Override + public void storeResourceVideo(Integer rid, Integer duration, String poster) { + resourceVideoService.create(rid, duration, poster); + } } diff --git a/src/main/java/xyz/playedu/api/service/impl/UploadServiceImpl.java b/src/main/java/xyz/playedu/api/service/impl/UploadServiceImpl.java new file mode 100644 index 0000000..b076b7d --- /dev/null +++ b/src/main/java/xyz/playedu/api/service/impl/UploadServiceImpl.java @@ -0,0 +1,91 @@ +package xyz.playedu.api.service.impl; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import org.springframework.web.multipart.MultipartFile; +import xyz.playedu.api.constant.BackendConstant; +import xyz.playedu.api.domain.Resource; +import xyz.playedu.api.exception.ServiceException; +import xyz.playedu.api.service.MinioService; +import xyz.playedu.api.service.ResourceCategoryService; +import xyz.playedu.api.service.ResourceService; +import xyz.playedu.api.service.UploadService; +import xyz.playedu.api.util.Base64Util; +import xyz.playedu.api.util.HelperUtil; + +/** + * @Author 杭州白书科技有限公司 + * @create 2023/3/8 14:02 + */ +@Service +public class UploadServiceImpl implements UploadService { + + @Autowired + private ResourceCategoryService resourceCategoryService; + + @Autowired + private ResourceService resourceService; + + @Autowired + private MinioService minioService; + + @Override + public Resource storeMinio(MultipartFile file, Integer cid) throws ServiceException { + if (file == null || file.isEmpty() || file.getOriginalFilename() == null) { + throw new ServiceException("请上传文件"); + } + + // 文件后缀名校验 + String filename = file.getOriginalFilename(); + String ext = HelperUtil.fileExt(filename); + String type = BackendConstant.RESOURCE_EXT_2_TYPE.get(ext); + if (type == null) { + throw new ServiceException("格式不支持"); + } + + // content-type校验 + String contentType = file.getContentType(); + String safeContentType = BackendConstant.RESOURCE_EXT_2_CONTENT_TYPE.get(ext); + if (safeContentType == null || !safeContentType.equals(contentType)) { + throw new ServiceException("格式不支持"); + } + + // 分类校验 + if (cid != null && !cid.equals(0) && resourceCategoryService.find(cid, type) == null) { + throw new ServiceException("分类不存在"); + } + + // 上传原文件的文件名 + String oFilename = filename.replaceAll("." + ext, ""); + // 自定义新的存储文件名 + String newFilename = HelperUtil.randomString(32) + "." + ext; + String savePath = BackendConstant.RESOURCE_TYPE_2_DIR.get(type) + newFilename; + + // 保存文件 + String url = minioService.saveFile(file, savePath, contentType); + // 上传记录 + return resourceService.create(cid, type, oFilename, ext, file.getSize(), BackendConstant.STORAGE_DRIVER_MINIO, "", savePath, url); + } + + @Override + public Resource storeBase64Image(String content, Integer categoryId) throws ServiceException { + // data:image/jpeg;base64, + String[] base64Rows = content.split(","); + String contentType = base64Rows[0].replaceAll("data:", "").replaceAll(";base64", "").toLowerCase(); + String ext = contentType.replaceAll("image/", ""); + String type = BackendConstant.RESOURCE_EXT_2_TYPE.get(ext); + String safeContentType = BackendConstant.RESOURCE_EXT_2_CONTENT_TYPE.get(ext); + if (type == null || safeContentType == null || !safeContentType.equals(contentType)) { + throw new ServiceException("格式不支持"); + } + byte[] binary = Base64Util.decode(base64Rows[1]); + + String filename = HelperUtil.randomString(32) + "." + ext; + String savePath = BackendConstant.RESOURCE_TYPE_2_DIR.get(type) + filename; + + // 保存文件 + String url = minioService.saveBytes(binary, savePath, contentType); + // 上传记录 + return resourceService.create(categoryId, type, filename, ext, (long) binary.length, BackendConstant.STORAGE_DRIVER_MINIO, "", savePath, url); + } +} diff --git a/src/main/resources/mapper/ResourceMapper.xml b/src/main/resources/mapper/ResourceMapper.xml index 3571566..41a20c8 100644 --- a/src/main/resources/mapper/ResourceMapper.xml +++ b/src/main/resources/mapper/ResourceMapper.xml @@ -16,12 +16,15 @@ + + id,type,category_id, name,extension,size, disk,file_id,path, - url,created_at + url,created_at,parent_id, + is_hidden