Selaa lähdekoodia

初始化分块接口,去除file入参,改成json传参

tsurumure 3 kuukautta sitten
vanhempi
commit
205e7463d5

+ 1 - 1
src/main/java/com/backendsys/modules/sdk/douyincloud/tos/service/DouyinTosService.java

@@ -25,7 +25,7 @@ public interface DouyinTosService {
 
 
     // [抖音云TOS] 初始化分块上传
-    CreateMultipartUploadOutput initiateMultipartUpload(MultipartFile multipartFile);
+    CreateMultipartUploadOutput initiateMultipartUpload(String filename);
     // [抖音云TOS] 上传分块
     UploadPartV2Output uploadPart(MultipartFile multipartFile, String upload_id, String object_key, Integer partNumber);
     // [抖音云TOS] 完成分块上传

+ 1 - 2
src/main/java/com/backendsys/modules/sdk/douyincloud/tos/service/impl/DouyinTosServiceImpl.java

@@ -202,12 +202,11 @@ public class DouyinTosServiceImpl implements DouyinTosService {
      * [抖音云TOS] 初始化分块上传
      */
     @Override
-    public CreateMultipartUploadOutput initiateMultipartUpload(MultipartFile multipartFile) {
+    public CreateMultipartUploadOutput initiateMultipartUpload(String filename) {
         TOSV2 tos = new TOSV2ClientBuilder().build(REGION, ENDPOINT, ACCESS_KEY_ID, SECRET_ACCESS_KEY);
         try {
 
             // 使用临时文件夹 (/temp) + UUID文件名
-            String filename = CommonUtil.generateUUIDFilename(multipartFile);
             String object_key = "temp/" + filename;
             System.out.println("InitiateMultipartUpload object: " + object_key);
 

+ 1 - 1
src/main/java/com/backendsys/modules/sdk/tencentcloud/cos/service/TencentCosService.java

@@ -30,7 +30,7 @@ public interface TencentCosService {
 
 
     // [腾讯云COS] 初始化分块上传
-    InitiateMultipartUploadResult initiateMultipartUpload(MultipartFile multipartFile);
+    InitiateMultipartUploadResult initiateMultipartUpload(String filename);
     // [腾讯云COS] 上传分块
     UploadPartResult uploadPart(MultipartFile multipartFile, String upload_id, String object_key, Integer partNumber);
     // [腾讯云COS] 完成分块上传

+ 1 - 4
src/main/java/com/backendsys/modules/sdk/tencentcloud/cos/service/impl/TencentCosServiceImpl.java

@@ -248,15 +248,12 @@ public class TencentCosServiceImpl implements TencentCosService {
     // [腾讯云COS] 初始化分块上传
     // https://cloud.tencent.com/document/product/436/65935#67d1955e-8784-4b9e-b12e-4f28f701f7eb
     @Override
-    public InitiateMultipartUploadResult initiateMultipartUpload(MultipartFile multipartFile) {
-
-        if (multipartFile.isEmpty()) throw new CustException("file 文件不能为空");
+    public InitiateMultipartUploadResult initiateMultipartUpload(String filename) {
 
         COSClient cosClient = getClient();
         try {
 
             // 使用临时文件夹 (/temp) + UUID文件名
-            String filename = CommonUtil.generateUUIDFilename(multipartFile);
             String object_key = "temp/" + filename;
             System.out.println("initiateMultipartUpload object: " + object_key);
 

+ 6 - 18
src/main/java/com/backendsys/modules/upload/controller/SysFileMultipartController.java

@@ -2,16 +2,15 @@ package com.backendsys.modules.upload.controller;
 
 import com.backendsys.modules.common.aspect.SysLog;
 import com.backendsys.modules.common.utils.Result;
+import com.backendsys.modules.upload.entity.MultipartUploadParams;
+import com.backendsys.modules.upload.entity.SysFile;
 import com.backendsys.modules.upload.service.SysFileMultipartService;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.security.access.prepost.PreAuthorize;
 import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 import org.springframework.web.multipart.MultipartFile;
 
 
@@ -34,12 +33,9 @@ public class SysFileMultipartController {
     @Operation(summary = "初始化分块上传")
     @PreAuthorize("@sr.hasPermission(1.1)")
     @PostMapping("/api/upload/multipartUploadInit")
-    public Result multipartUploadInit(@RequestParam("file") MultipartFile multipartFile, Long category_id, Integer upload_chunk_count, String md5) {
-
-        System.out.println("初始化分块上传(调试)");
-
-        return Result.success();
-//        return Result.success().put("data", sysFileMultipartService.multipartUploadInit(multipartFile, category_id, upload_chunk_count, md5));
+//    public Result multipartUploadInit(Long category_id, Integer upload_chunk_count, String md5) {
+    public Result multipartUploadInit(@Validated(MultipartUploadParams.Init.class) @RequestBody MultipartUploadParams multipartUploadParams) {
+        return Result.success().put("data", sysFileMultipartService.multipartUploadInit(multipartUploadParams));
     }
 
     @SysLog("上传分块")
@@ -65,12 +61,4 @@ public class SysFileMultipartController {
         return Result.success().put("data", sysFileMultipartService.listParts(upload_id, object_key));
     }
 
-    @SysLog("获取文件MD5 (临时)")
-    @Operation(summary = "获取文件MD5 (临时)")
-    @PreAuthorize("@sr.hasPermission(1.1)")
-    @PostMapping("/api/upload/getFileMd5")
-    public Result getFileMd5(@RequestParam("file") MultipartFile multipartFile, Long category_id, Integer upload_chunk_count, String md5) {
-        return Result.success().put("data", sysFileMultipartService.multipartUploadInit(multipartFile, category_id, upload_chunk_count, md5));
-    }
-
 }

+ 26 - 0
src/main/java/com/backendsys/modules/upload/entity/MultipartUploadParams.java

@@ -0,0 +1,26 @@
+package com.backendsys.modules.upload.entity;
+
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Size;
+import lombok.Data;
+
+@Data
+public class MultipartUploadParams {
+
+    public static interface Init{}
+
+    @NotEmpty(message = "文件名称不能为空", groups = { Init.class })
+    @Size(max = 50, message = "文件名称长度不超过 {max} 字符", groups = { Init.class })
+    private String filename;
+    private Long category_id;
+    @NotNull(message = "分块数量不能为空", groups = { Init.class })
+    private Integer upload_chunk_count;
+    @NotEmpty(message = "md5 不能为空", groups = { Init.class })
+    private String md5;
+    @NotEmpty(message = "content_type 不能为空", groups = { Init.class })
+    private String content_type;
+    @NotNull(message = "size 不能为空", groups = { Init.class })
+    private Long size;
+
+}

+ 2 - 1
src/main/java/com/backendsys/modules/upload/service/SysFileMultipartService.java

@@ -1,5 +1,6 @@
 package com.backendsys.modules.upload.service;
 
+import com.backendsys.modules.upload.entity.MultipartUploadParams;
 import com.backendsys.modules.upload.entity.SysFile;
 import com.qcloud.cos.model.PartListing;
 import org.springframework.web.multipart.MultipartFile;
@@ -9,7 +10,7 @@ import java.util.Map;
 public interface SysFileMultipartService {
 
     // 1.初始化分块上传
-    Map<String, Object> multipartUploadInit(MultipartFile multipartFile, Long category_id, Integer upload_chunk_count, String md5);
+    Map<String, Object> multipartUploadInit(MultipartUploadParams multipartUploadParams);
     // 2.上传分块
     Map<String, Object> multipartUpload(MultipartFile multipartFile, String upload_id, Integer upload_chunk_index);
     // 3.完成分块上传

+ 70 - 81
src/main/java/com/backendsys/modules/upload/service/impl/SysFileMultipartServiceImpl.java

@@ -16,6 +16,7 @@ import com.backendsys.modules.system.entity.SysCommon;
 import com.backendsys.modules.system.entity.SysUser;
 import com.backendsys.modules.system.service.SysCommonService;
 import com.backendsys.modules.upload.dao.SysFileDao;
+import com.backendsys.modules.upload.entity.MultipartUploadParams;
 import com.backendsys.modules.upload.entity.SysFile;
 import com.backendsys.modules.upload.enums.StyleEnums;
 import com.backendsys.modules.upload.service.SysFileMultipartService;
@@ -98,25 +99,22 @@ public class SysFileMultipartServiceImpl implements SysFileMultipartService {
     }
 
     // [方法] 上传事件
-    private SysFile uploadInitEvent(MultipartFile multipartFile, Long category_id, Integer target, Integer upload_chunk_count, String md5) {
+    private SysFile uploadInitEvent(MultipartUploadParams multipartUploadParams, Integer target) {
         System.out.println("[系统配置] 上传目标(-1:本地, 1:腾讯云, 2:阿里云, 3.抖音云): " + target);
 
-        String filename = multipartFile.getOriginalFilename();
-        if (filename.length() > 50) throw new CustException("文件名长度不能超过 50 字符");
-
         String target_label = StyleEnums.targetToLabel(target);
         String upload_id = null;
         String object_key = null;
 
         // target: 上传目标 (-1:本地, 1:腾讯云, 2:阿里云, 3.抖音云)
         if (target == 1) {
-            InitiateMultipartUploadResult uploadResult = tencentCosService.initiateMultipartUpload(multipartFile);
+            InitiateMultipartUploadResult uploadResult = tencentCosService.initiateMultipartUpload(multipartUploadParams.getFilename());
             upload_id = uploadResult.getUploadId();
             object_key = uploadResult.getKey();
         }
         // 3: 抖音云
         if (target == 3) {
-            CreateMultipartUploadOutput uploadResult = douyinTosService.initiateMultipartUpload(multipartFile);
+            CreateMultipartUploadOutput uploadResult = douyinTosService.initiateMultipartUpload(multipartUploadParams.getFilename());
             upload_id = uploadResult.getUploadID();
             object_key = uploadResult.getKey();
         }
@@ -128,18 +126,18 @@ public class SysFileMultipartServiceImpl implements SysFileMultipartService {
 
         // [新增] 上传文件记录
         SysFile sysFileEntity = new SysFile();
-        sysFileEntity.setCategory_id(category_id);
+        sysFileEntity.setCategory_id(multipartUploadParams.getCategory_id());
         sysFileEntity.setUser_id(httpRequestUtil.getUserId());
         sysFileEntity.setUpload_id(upload_id);
-        sysFileEntity.setUpload_chunk_count(upload_chunk_count);
+        sysFileEntity.setUpload_chunk_count(multipartUploadParams.getUpload_chunk_count());
         sysFileEntity.setUpload_chunk_index(0);
 //        sysFileEntity.setName(FileNameUtil.getName(object_key));
-        sysFileEntity.setName(filename);
+        sysFileEntity.setName(multipartUploadParams.getFilename());
         sysFileEntity.setObject_key(object_key);
         sysFileEntity.setTarget(target);
-        sysFileEntity.setContent_type(multipartFile.getContentType());
-        sysFileEntity.setSize(multipartFile.getSize());
-        sysFileEntity.setMd5(md5);
+        sysFileEntity.setContent_type(multipartUploadParams.getContent_type());
+        sysFileEntity.setSize(multipartUploadParams.getSize());
+        sysFileEntity.setMd5(multipartUploadParams.getMd5());
         sysFileDao.insert(sysFileEntity);
 
         return sysFileEntity;
@@ -148,14 +146,7 @@ public class SysFileMultipartServiceImpl implements SysFileMultipartService {
 
     // 1.初始化分块上传 (获得 upload_id, object_key)
     @Override
-    public Map<String, Object> multipartUploadInit(MultipartFile multipartFile, Long category_id, Integer upload_chunk_count, String md5) {
-
-//        if (multipartFile.isEmpty()) throw new CustException("file 上传文件不能为空");
-//        if (upload_chunk_count == null) throw new CustException("upload_chunk_count 分块数量不能为空");
-//        if (md5.isEmpty()) throw new CustException("md5 不能为空");
-//
-//        String filename = multipartFile.getOriginalFilename();
-//        if (filename.length() > 50) throw new CustException("文件名长度不能超过 50 字符");
+    public Map<String, Object> multipartUploadInit(MultipartUploadParams multipartUploadParams) {
 
 //        // 按用户加锁
 //        RLock lock = redissonClient.getLock("lock::multipart-upload::user-id::" + SecurityUtil.getUserId());
@@ -174,67 +165,65 @@ public class SysFileMultipartServiceImpl implements SysFileMultipartService {
 
         SysFile sysFileEntity = null;
 
-        return Map.of("test", 1);
-
-//        // [弃用] 获取大文件流需要比较久的时间
-//        // String md5 = DigestUtil.md5Hex(multipartFile.getInputStream());
-//
-//        // 如果开启了 MD5秒传,则判断文件是否上传过,是的话就直接返回
-//        // [系统配置] 是否启用文件MD5查重 (仅判断用户自己上传过的文件)
-//        // - 存在,则根据文件MD5 判断是否上传过文件 (仅更新时间,不上传已存在的文件,允许更新文件分类)
-//        // - 存在,如果存在两个相同 md5 以上的文件,则需要排重后再上传 (如果是不同用户
-//        // - 不存在,则走上传流程
-//        Boolean is_exist = false;
-//        if (UPLOAD_MD5_DUPLICATE.get()) {
-//
-//            // 排除文件异常的情况(出现两个以上相同MD5的文件)
-//            LambdaQueryWrapper<SysFile> wrapperFile = new LambdaQueryWrapper<>();
-//            wrapperFile.eq(SysFile::getMd5, md5);
-//            wrapperFile.eq(SysFile::getUser_id, SecurityUtil.getUserId());
-//
-//            // [DB] 查询已存在的文件分块记录 (只有完全上传成功,才会有 MD5)
-//            // - 异常情况:如果有两个相同的文件,一个上传50%,一个上传成功,就会出现以下这种情况,需要手动解决
-//            List<SysFile> sysFileEntityList = sysFileDao.selectList(wrapperFile);
-//            if (sysFileEntityList != null && sysFileEntityList.size() > 1) {
-//                throw new CustException("存在 " + sysFileEntityList.size() + " 个相同MD5 (" + md5 + ") 的文件,请删除后再重新上传");
-//            }
-//
-//            if (sysFileEntityList != null && sysFileEntityList.size() > 0) {
-//                is_exist = true;
-//                // 将已存在的文件,赋值
-//                sysFileEntity = sysFileEntityList.get(0);
-//                // [DB] 更新文件 (文件分类、上传时间)
-//                sysFileEntity.setCategory_id(category_id);
-//                sysFileEntity.setUpload_time(DateUtil.now());
-//                sysFileDao.updateById(sysFileEntity);
-//            } else {
-//                // [DB] 创建新的文件
-//                sysFileEntity = uploadInitEvent(multipartFile, category_id, UPLOAD_TARGET.get(), upload_chunk_count, md5);
-//                // [格式化] 封面 (图片类型)
-//                sysFileEntity = setThumbUrl(sysFileEntity, UPLOAD_THUMB_SIZE.get(), UPLOAD_THUMB_SIZE.get(), StyleEnums.THUMB_BACKGROUND.getValue());
-//            }
-//
-//        } else {
-//            // 不开启 MD5秒 传,则直接初始化分块
-//            // [DB] 创建新的文件
-//            sysFileEntity = uploadInitEvent(multipartFile, category_id, UPLOAD_TARGET.get(), upload_chunk_count, md5);
-//            // [格式化] 封面 (图片类型)
-//            sysFileEntity = setThumbUrl(sysFileEntity, UPLOAD_THUMB_SIZE.get(), UPLOAD_THUMB_SIZE.get(), StyleEnums.THUMB_BACKGROUND.getValue());
-//        }
-//
-//        Map<String, Object> resp = new LinkedHashMap<>();
-//        resp.put("target", UPLOAD_TARGET.get());
-//        resp.put("target_label", StyleEnums.targetToLabel(UPLOAD_TARGET.get()));
-//        resp.put("upload_chunk_count", upload_chunk_count);
-//        resp.put("upload_id", sysFileEntity.getUpload_id());
-//        resp.put("object_key", sysFileEntity.getObject_key());
-//        resp.put("md5", md5);
-//        resp.put("is_exist", is_exist);
-//        resp.put("file_info", is_exist ? sysFileEntity : null);
-//        return resp;
-//
-////        } catch (InterruptedException e) { throw new RuntimeException(e);
-////        } finally { lock.unlock(); }
+        // [弃用] 获取大文件流需要比较久的时间
+        // String md5 = DigestUtil.md5Hex(multipartFile.getInputStream());
+
+        // 如果开启了 MD5秒传,则判断文件是否上传过,是的话就直接返回
+        // [系统配置] 是否启用文件MD5查重 (仅判断用户自己上传过的文件)
+        // - 存在,则根据文件MD5 判断是否上传过文件 (仅更新时间,不上传已存在的文件,允许更新文件分类)
+        // - 存在,如果存在两个相同 md5 以上的文件,则需要排重后再上传 (如果是不同用户
+        // - 不存在,则走上传流程
+        Boolean is_exist = false;
+        if (UPLOAD_MD5_DUPLICATE.get()) {
+
+            // 排除文件异常的情况(出现两个以上相同MD5的文件)
+            LambdaQueryWrapper<SysFile> wrapperFile = new LambdaQueryWrapper<>();
+            wrapperFile.eq(SysFile::getMd5, multipartUploadParams.getMd5());
+            wrapperFile.eq(SysFile::getUser_id, SecurityUtil.getUserId());
+
+            // [DB] 查询已存在的文件分块记录 (只有完全上传成功,才会有 MD5)
+            // - 异常情况:如果有两个相同的文件,一个上传50%,一个上传成功,就会出现以下这种情况,需要手动解决
+            List<SysFile> sysFileEntityList = sysFileDao.selectList(wrapperFile);
+            if (sysFileEntityList != null && sysFileEntityList.size() > 1) {
+                throw new CustException("存在 " + sysFileEntityList.size() + " 个相同MD5 (" + multipartUploadParams.getMd5() + ") 的文件,请删除后再重新上传");
+            }
+
+            if (sysFileEntityList != null && sysFileEntityList.size() > 0) {
+                is_exist = true;
+                // 将已存在的文件,赋值
+                sysFileEntity = sysFileEntityList.get(0);
+                // [DB] 更新文件 (文件分类、上传时间)
+                sysFileEntity.setCategory_id(multipartUploadParams.getCategory_id());
+                sysFileEntity.setUpload_time(DateUtil.now());
+                sysFileDao.updateById(sysFileEntity);
+            } else {
+                // [DB] 创建新的文件
+                sysFileEntity = uploadInitEvent(multipartUploadParams, UPLOAD_TARGET.get());
+                // [格式化] 封面 (图片类型)
+                sysFileEntity = setThumbUrl(sysFileEntity, UPLOAD_THUMB_SIZE.get(), UPLOAD_THUMB_SIZE.get(), StyleEnums.THUMB_BACKGROUND.getValue());
+            }
+
+        } else {
+            // 不开启 MD5秒 传,则直接初始化分块
+            // [DB] 创建新的文件
+            sysFileEntity = uploadInitEvent(multipartUploadParams, UPLOAD_TARGET.get());
+            // [格式化] 封面 (图片类型)
+            sysFileEntity = setThumbUrl(sysFileEntity, UPLOAD_THUMB_SIZE.get(), UPLOAD_THUMB_SIZE.get(), StyleEnums.THUMB_BACKGROUND.getValue());
+        }
+
+        Map<String, Object> resp = new LinkedHashMap<>();
+        resp.put("target", UPLOAD_TARGET.get());
+        resp.put("target_label", StyleEnums.targetToLabel(UPLOAD_TARGET.get()));
+        resp.put("upload_chunk_count", multipartUploadParams.getUpload_chunk_count());
+        resp.put("upload_id", sysFileEntity.getUpload_id());
+        resp.put("object_key", sysFileEntity.getObject_key());
+        resp.put("md5", multipartUploadParams.getMd5());
+        resp.put("is_exist", is_exist);
+        resp.put("file_info", is_exist ? sysFileEntity : null);
+        return resp;
+
+//        } catch (InterruptedException e) { throw new RuntimeException(e);
+//        } finally { lock.unlock(); }
     }
 
     // 2.上传分块