lyhzzz 8 months ago
parent
commit
3a629dc29e
25 changed files with 964 additions and 22 deletions
  1. 1 0
      pom.xml
  2. 3 0
      src/main/java/com/fdkankan/fusion/common/ResultCode.java
  3. 338 0
      src/main/java/com/fdkankan/fusion/common/util/MinIoChunkUtils.java
  4. 5 0
      src/main/java/com/fdkankan/fusion/common/util/ShellUtil.java
  5. 2 0
      src/main/java/com/fdkankan/fusion/config/MinIOConfig.java
  6. 2 0
      src/main/java/com/fdkankan/fusion/controller/SceneController.java
  7. 113 9
      src/main/java/com/fdkankan/fusion/controller/UploadController.java
  8. 46 0
      src/main/java/com/fdkankan/fusion/controller/UploadSceneController.java
  9. 97 0
      src/main/java/com/fdkankan/fusion/entity/UploadChunk.java
  10. 66 0
      src/main/java/com/fdkankan/fusion/entity/UploadScene.java
  11. 5 5
      src/main/java/com/fdkankan/fusion/generate/AutoGenerate.java
  12. 50 4
      src/main/java/com/fdkankan/fusion/httpClient/FdService.java
  13. 3 4
      src/main/java/com/fdkankan/fusion/httpClient/client/FdKKClient.java
  14. 19 0
      src/main/java/com/fdkankan/fusion/httpClient/request/UploadEditSceneParam.java
  15. 18 0
      src/main/java/com/fdkankan/fusion/mapper/IUploadChunkMapper.java
  16. 18 0
      src/main/java/com/fdkankan/fusion/mapper/IUploadSceneMapper.java
  17. 10 0
      src/main/java/com/fdkankan/fusion/request/UploadSceneParam.java
  18. 25 0
      src/main/java/com/fdkankan/fusion/response/UploadChunkVo.java
  19. 19 0
      src/main/java/com/fdkankan/fusion/service/IUploadChunkService.java
  20. 17 0
      src/main/java/com/fdkankan/fusion/service/IUploadSceneService.java
  21. 39 0
      src/main/java/com/fdkankan/fusion/service/impl/UploadChunkServiceImpl.java
  22. 57 0
      src/main/java/com/fdkankan/fusion/service/impl/UploadSceneServiceImpl.java
  23. 1 0
      src/main/resources/application.yaml
  24. 5 0
      src/main/resources/mapper/fusion/UploadChunkMapper.xml
  25. 5 0
      src/main/resources/mapper/fusion/UploadSceneMapper.xml

+ 1 - 0
pom.xml

@@ -24,6 +24,7 @@
             <version>3.0.0-SNAPSHOT</version>
         </dependency>
 
+
         <dependency>
             <groupId>mysql</groupId>
             <artifactId>mysql-connector-java</artifactId>

+ 3 - 0
src/main/java/com/fdkankan/fusion/common/ResultCode.java

@@ -72,6 +72,9 @@ public enum ResultCode {
     CAMERA_VERSION_EXIT(7025, "相机版本号已存在"),
     CAMERA_VERSION_NOTEXIT(7026, "相机版本号不存在"),
     CAMERA_VERSION_STATUS_ERROR(7027, "相机版本状态错误"),
+    FILE_EXITS(7028, "该文件已上传"),
+    COMPOSE_FILE_ERROR(7029, "合并文件失败"),
+    TYPE_ERROR(7030, "上传资源类型错误"),
 
 
     ;

+ 338 - 0
src/main/java/com/fdkankan/fusion/common/util/MinIoChunkUtils.java

@@ -0,0 +1,338 @@
+package com.fdkankan.fusion.common.util;
+
+import com.fdkankan.fusion.config.MinIOConfig;
+import io.minio.*;
+import io.minio.http.Method;
+import io.minio.messages.Item;
+import lombok.SneakyThrows;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+/**
+ * @ClassName UploadApiController
+ * @Description TODO
+ * @Author Ryan.
+ * @Emial_AND_OICQ ryan.tang@cyberwisdom.net AND 100792057
+ * @Date 2020/9/7 13:20
+ * @Version 1.0
+ **/
+@Component
+public class MinIoChunkUtils implements InitializingBean {
+
+    private static String url;
+
+    private static String accessKey;
+
+    private static String secretKey;
+
+
+    public static String chunkBucKet;
+
+    private static MinioClient minioClient;
+
+    /**
+     * 排序
+     */
+    public final static boolean SORT = true;
+    /**
+     * 不排序
+     */
+    public final static boolean NOT_SORT = false;
+    /**
+     * 默认过期时间(分钟)
+     */
+    private final static Integer DEFAULT_EXPIRY = 60;
+
+
+
+    @Override
+    public void afterPropertiesSet() throws Exception {
+        minioClient = MinioClient.builder().endpoint(url).credentials(accessKey,secretKey).build();
+		//方便管理分片文件,则单独创建一个分片文件的存储桶
+        if (!isBucketExist(chunkBucKet)){
+            createBucket(chunkBucKet);
+        }
+    }
+
+    /**
+     * 初始化MinIo对象
+     * 非此工具类请勿使用该方法
+     */
+    @Autowired
+    MinIOConfig minIOConfig;
+    @PostConstruct
+    public void init(){
+        url = minIOConfig.getEndpoint();
+        accessKey =minIOConfig.getAccessKey();
+        secretKey = minIOConfig.getSecretKey();
+        chunkBucKet = minIOConfig.getBucketChunk();
+    }
+
+    /**
+     * 存储桶是否存在
+     * @param bucketName 存储桶名称
+     * @return true/false
+     */
+    @SneakyThrows
+    public static boolean isBucketExist(String bucketName){
+        return minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
+    }
+
+    /**
+     * 创建存储桶
+     * @param bucketName 存储桶名称
+     * @return true/false
+     */
+    @SneakyThrows
+    public static boolean createBucket(String bucketName){
+        minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
+        return true;
+    }
+
+    /**
+     * 获取访问对象的外链地址
+     * @param bucketName 存储桶名称
+     * @param objectName 对象名称
+     * @param expiry 过期时间(分钟) 最大为7天 超过7天则默认最大值
+     * @return viewUrl
+     */
+    @SneakyThrows
+    public static String getObjectUrl(String bucketName,String objectName,Integer expiry){
+        expiry = expiryHandle(expiry);
+        return minioClient.getPresignedObjectUrl(
+                GetPresignedObjectUrlArgs.builder()
+                        .method(Method.GET)
+                        .bucket(bucketName)
+                        .object(objectName)
+                        .expiry(expiry)
+                        .build()
+        );
+    }
+
+    /**
+     * 创建上传文件对象的外链
+     * @param bucketName 存储桶名称
+     * @param objectName 欲上传文件对象的名称
+     * @param expiry 过期时间(分钟) 最大为7天 超过7天则默认最大值
+     * @return uploadUrl
+     */
+    @SneakyThrows
+    public static String createUploadUrl(String bucketName,String objectName,Integer expiry){
+        expiry = expiryHandle(expiry);
+        return minioClient.getPresignedObjectUrl(
+                GetPresignedObjectUrlArgs.builder()
+                        .method(Method.PUT)
+                        .bucket(bucketName)
+                        .object(objectName)
+                        .expiry(expiry)
+                        .build()
+        );
+    }
+
+    /**
+     * 创建上传文件对象的外链
+     * @param bucketName 存储桶名称
+     * @param objectName 欲上传文件对象的名称
+     * @return uploadUrl
+     */
+    public static String createUploadUrl(String bucketName,String objectName){
+        return createUploadUrl(bucketName,objectName,DEFAULT_EXPIRY);
+    }
+
+    /**
+     * 批量创建分片上传外链
+     * @param bucketName 存储桶名称
+     * @param objectMD5 欲上传分片文件主文件的MD5
+     * @param chunkCount 分片数量
+     * @return uploadChunkUrls
+     */
+    public static List<String> createUploadChunkUrlList(String bucketName,String objectMD5,Integer chunkCount){
+        if (null == bucketName){
+            bucketName = chunkBucKet;
+        }
+        if (null == objectMD5){
+            return null;
+        }
+        objectMD5 += "/";
+        if(null == chunkCount || 0 == chunkCount){
+            return null;
+        }
+        List<String> urlList = new ArrayList<>(chunkCount);
+        for (int i = 1; i <= chunkCount; i++){
+            String objectName = objectMD5 + i + ".chunk";
+            urlList.add(createUploadUrl(bucketName,objectName,DEFAULT_EXPIRY));
+        }
+        return urlList;
+    }
+
+    /**
+     * 创建指定序号的分片文件上传外链
+     * @param bucketName 存储桶名称
+     * @param objectMD5 欲上传分片文件主文件的MD5
+     * @param partNumber 分片序号
+     * @return uploadChunkUrl
+     */
+    public static String createUploadChunkUrl(String bucketName,String objectMD5,String partNumber){
+        if (null == bucketName){
+            bucketName = chunkBucKet;
+        }
+        if (null == objectMD5){
+            return null;
+        }
+        objectMD5 += "/" + partNumber + ".chunk";
+        return createUploadUrl(bucketName,objectMD5,DEFAULT_EXPIRY);
+    }
+
+    /**
+     * 获取对象文件名称列表
+     * @param bucketName 存储桶名称
+     * @param prefix 对象名称前缀
+     * @param sort 是否排序(升序)
+     * @return objectNames
+     */
+    @SneakyThrows
+    public static List<String> listObjectNames(String bucketName,String prefix,Boolean sort){
+        ListObjectsArgs listObjectsArgs;
+        if(null == prefix){
+            listObjectsArgs = ListObjectsArgs.builder()
+                    .bucket(bucketName)
+                    .recursive(true)
+                    .build();
+        }else {
+            listObjectsArgs = ListObjectsArgs.builder()
+                    .bucket(bucketName)
+                    .prefix(prefix)
+                    .recursive(true)
+                    .build();
+        }
+        Iterable<Result<Item>> chunks = minioClient.listObjects(listObjectsArgs);
+        List<String> chunkPaths = new ArrayList<>();
+        for (Result<Item> item : chunks){
+            chunkPaths.add(item.get().objectName());
+        }
+        if (sort){
+            return chunkPaths.stream().distinct().collect(Collectors.toList());
+        }
+        return chunkPaths;
+    }
+
+    /**
+     * 获取对象文件名称列表
+     * @param bucketName 存储桶名称
+     * @param prefix 对象名称前缀
+     * @return objectNames
+     */
+    public static List<String> listObjectNames(String bucketName,String prefix){
+        return listObjectNames(bucketName, prefix, NOT_SORT);
+    }
+
+    /**
+     * 获取分片文件名称列表
+     * @param bucketName 存储桶名称
+     * @param ObjectMd5 对象Md5
+     * @return objectChunkNames
+     */
+    public static List<String> listChunkObjectNames(String bucketName,String ObjectMd5){
+        if (null == bucketName){
+            bucketName = chunkBucKet;
+        }
+        if (null == ObjectMd5){
+            return null;
+        }
+        return listObjectNames(bucketName,ObjectMd5,SORT);
+    }
+
+    /**
+     * 获取分片名称地址HashMap key=分片序号 value=分片文件地址
+     * @param bucketName 存储桶名称
+     * @param ObjectMd5 对象Md5
+     * @return objectChunkNameMap
+     */
+    public static Map<Integer,String> mapChunkObjectNames(String bucketName, String ObjectMd5){
+        if (null == bucketName){
+            bucketName = chunkBucKet;
+        }
+        if (null == ObjectMd5){
+            return new HashMap<>();
+        }
+        List<String> chunkPaths = listObjectNames(bucketName,ObjectMd5);
+        if (null == chunkPaths || chunkPaths.size() == 0){
+            return new HashMap<>();
+        }
+        Map<Integer,String> chunkMap = new HashMap<>(chunkPaths.size());
+        for (String chunkName : chunkPaths) {
+            Integer partNumber = Integer.parseInt(chunkName.substring(chunkName.indexOf("/") + 1,chunkName.lastIndexOf(".")));
+            chunkMap.put(partNumber,chunkName);
+        }
+        return chunkMap;
+    }
+
+    /**
+     * 合并分片文件成对象文件
+     * @param chunkBucKetName 分片文件所在存储桶名称
+     * @param composeBucketName 合并后的对象文件存储的存储桶名称
+     * @param chunkNames 分片文件名称集合
+     * @param objectName 合并后的对象文件名称
+     * @return true/false
+     */
+    @SneakyThrows
+    public static boolean composeObject(String chunkBucKetName,String composeBucketName,List<String> chunkNames,String objectName){
+        if (null == chunkBucKetName){
+            chunkBucKetName = chunkBucKet;
+        }
+        List<ComposeSource> sourceObjectList = new ArrayList<>(chunkNames.size());
+        for (String chunk : chunkNames){
+            sourceObjectList.add(
+                    ComposeSource.builder()
+                            .bucket(chunkBucKetName)
+                            .object(chunk)
+                            .build()
+            );
+        }
+        minioClient.composeObject(
+                ComposeObjectArgs.builder()
+                        .bucket(composeBucketName)
+                        .object(objectName)
+                        .sources(sourceObjectList)
+                        .build()
+        );
+        return true;
+    }
+
+    /**
+     * 合并分片文件成对象文件
+     * @param bucketName 存储桶名称
+     * @param chunkNames 分片文件名称集合
+     * @param objectName 合并后的对象文件名称
+     * @return true/false
+     */
+    public static boolean composeObject(String bucketName,List<String> chunkNames,String objectName){
+        return composeObject(chunkBucKet,bucketName,chunkNames,objectName);
+    }
+
+    /**
+     * 将分钟数转换为秒数
+     * @param expiry 过期时间(分钟数)
+     * @return expiry
+     */
+    private static int expiryHandle(Integer expiry){
+        expiry = expiry * 60;
+        if (expiry > 604800){
+            return 604800;
+        }
+        return expiry;
+    }
+    public static String buZero(Integer size,Integer index){
+        String numStr = String.valueOf(size);
+        return StringUtils.leftPad(String.valueOf(index),numStr.length()+1,'0');
+    }
+}

+ 5 - 0
src/main/java/com/fdkankan/fusion/common/util/ShellUtil.java

@@ -192,4 +192,9 @@ public class ShellUtil {
         String cmd = String.format(ShellCmd.FYUN_DOWN,"laser-data",srcPath,destPath,"minio",opType);
         execCmd(cmd);
     }
+    public static void yunDownloadChunk(String srcPath,String destPath){
+        String opType = srcPath.contains(".")? "file":"folder" ;
+        String cmd = String.format(ShellCmd.FYUN_DOWN,"fusion-chunk",srcPath,destPath,"minio",opType);
+        execCmd(cmd);
+    }
 }

+ 2 - 0
src/main/java/com/fdkankan/fusion/config/MinIOConfig.java

@@ -18,5 +18,7 @@ public class MinIOConfig {
     private String accessKey;
     @Value("${minio.secretKey}")
     private String secretKey;
+    @Value("${minio.bucketChunk}")
+    private String bucketChunk;
 
 }

+ 2 - 0
src/main/java/com/fdkankan/fusion/controller/SceneController.java

@@ -9,8 +9,10 @@ import com.fdkankan.fusion.common.util.UploadToOssUtil;
 import com.fdkankan.fusion.exception.BusinessException;
 import com.fdkankan.fusion.httpClient.request.LaserSceneParam;
 import com.fdkankan.fusion.request.ScenePram;
+import com.fdkankan.fusion.request.UploadSceneParam;
 import com.fdkankan.fusion.response.FileInfoVo;
 import com.fdkankan.fusion.response.SceneProEntityVo;
+import com.fdkankan.fusion.service.IScenePlusService;
 import com.fdkankan.fusion.service.ISceneService;
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.lang3.StringUtils;

+ 113 - 9
src/main/java/com/fdkankan/fusion/controller/UploadController.java

@@ -2,22 +2,24 @@ package com.fdkankan.fusion.controller;
 
 import com.fdkankan.fusion.common.FilePath;
 import com.fdkankan.fusion.common.ResultCode;
-import com.fdkankan.fusion.exception.BusinessException;
+import com.fdkankan.fusion.common.util.MinIoChunkUtils;
+import com.fdkankan.fusion.entity.UploadChunk;
 import com.fdkankan.fusion.common.ResultData;
-import com.fdkankan.fusion.common.ResultCode;
+import com.fdkankan.fusion.exception.BusinessException;
+import com.fdkankan.fusion.response.UploadChunkVo;
+import com.fdkankan.fusion.service.IUploadChunkService;
+import com.fdkankan.fusion.service.IUploadSceneService;
 import com.fdkankan.fusion.service.impl.UploadService;
 import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-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;
 
-import javax.annotation.Resource;
-import java.io.File;
-import java.util.UUID;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
 
 @RestController
 @RequestMapping("/upload")
@@ -33,4 +35,106 @@ public class UploadController {
 
         return ResultData.ok( uploadService.uploadFile(file,true,String.format(FilePath.File_OSS_PATH,environment,"")));
     }
+
+    @PostMapping("/getByFileMd5")
+    public ResultData getByFileMd5(@RequestBody UploadChunk uploadDto){
+        if(StringUtils.isBlank(uploadDto.getFileMd5()) ){
+            throw new BusinessException(ResultCode.MISSING_REQUIRED_PARAMETERS);
+        }
+        return ResultData.ok(uploadChunkService.getByFileMd5(uploadDto.getFileMd5()));
+    }
+
+
+    @Autowired
+    IUploadChunkService uploadChunkService;
+    @Autowired
+    IUploadSceneService uploadSceneService;
+    @PostMapping("/init-chunk-upload")
+    public ResultData initChunkUpload(@RequestBody UploadChunk uploadDto){
+        if(StringUtils.isBlank(uploadDto.getFileMd5()) || StringUtils.isBlank(uploadDto.getFileName())
+                || uploadDto.getChunkCount() == null || uploadDto.getFileSize() ==null){
+            throw new BusinessException(ResultCode.MISSING_REQUIRED_PARAMETERS);
+        }
+        //校验文件md5,该文件是否上传过
+        UploadChunk uploadChunk = uploadChunkService.getByFileMd5(uploadDto.getFileMd5());
+        if(uploadChunk != null){
+            if(uploadChunk.getUploadStatus() == 1){
+                throw new BusinessException(ResultCode.FILE_EXITS);
+            }
+            //续传
+            //获取到该文件已上传分片
+            Map<Integer,String> okChunkMap = MinIoChunkUtils.mapChunkObjectNames(MinIoChunkUtils.chunkBucKet,uploadDto.getFileMd5());
+
+            List<UploadChunkVo> uploadChunkVos  = new ArrayList<>();
+            for (int i = 1; i <= uploadDto.getChunkCount(); i++) {
+                //判断当前分片是否已经上传过了
+                if(!okChunkMap.containsKey(i)){
+                    //生成分片上传url
+                    UploadChunkVo url = new UploadChunkVo();
+                    url.setPartNumber(MinIoChunkUtils.buZero(uploadDto.getChunkCount(),i));
+                    url.setUploadUrl(MinIoChunkUtils.createUploadChunkUrl(MinIoChunkUtils.chunkBucKet,uploadDto.getFileMd5(),url.getPartNumber()));
+                    uploadChunkVos.add(url);
+                }
+            }
+            UploadChunkVo vo = new UploadChunkVo();
+            BeanUtils.copyProperties(uploadChunk,vo);
+            vo.setUploadChunkVos(uploadChunkVos);
+            return ResultData.ok(vo);
+        }
+        //初次上传和已有文件信息但未上传任何分片的情况下则直接生成所有上传url
+        List<String> uploadUrls = MinIoChunkUtils.createUploadChunkUrlList(MinIoChunkUtils.chunkBucKet,uploadDto.getFileMd5(),uploadDto.getChunkCount());
+        List<UploadChunkVo> uploadChunkVos  = new ArrayList<>();
+        for (int i = 1; i <= uploadUrls.size(); i++) {
+            UploadChunkVo url = new UploadChunkVo();
+            url.setPartNumber(MinIoChunkUtils.buZero(uploadUrls.size(),i));
+            url.setUploadUrl(MinIoChunkUtils.createUploadChunkUrl(MinIoChunkUtils.chunkBucKet,uploadDto.getFileMd5(),url.getPartNumber()));
+            uploadChunkVos.add(url);
+        }
+        String suffix = uploadDto.getFileName().substring(uploadDto.getFileName().lastIndexOf("."));
+
+        //向数据库中记录该文件的上传信息
+        UploadChunk uploadChunk2 = new UploadChunk();
+        uploadChunk2.setBucketName(MinIoChunkUtils.chunkBucKet);
+        uploadChunk2.setChunkCount(uploadDto.getChunkCount());
+        uploadChunk2.setFileMd5(uploadDto.getFileMd5());
+        uploadChunk2.setFileName(uploadDto.getFileName());
+        uploadChunk2.setSuffix(suffix);
+        uploadChunkService.save(uploadChunk2);
+
+        UploadChunkVo vo = new UploadChunkVo();
+        BeanUtils.copyProperties(uploadChunk2,vo);
+        vo.setUploadChunkVos(uploadChunkVos);
+        return ResultData.ok(vo);
+    }
+
+
+    @PostMapping("/compose-file")
+    public ResultData composeFile(@RequestBody UploadChunk uploadDto){
+        if(StringUtils.isBlank(uploadDto.getFileMd5()) ){
+            throw new BusinessException(ResultCode.MISSING_REQUIRED_PARAMETERS);
+        }
+        //根据md5获取所有分片文件名称(minio的文件名称 = 文件path)
+        List<String> chunks = MinIoChunkUtils.listChunkObjectNames(MinIoChunkUtils.chunkBucKet,uploadDto.getFileMd5());
+
+        //自定义文件名称
+        String fileName = uploadDto.getFileName();
+        String suffix = fileName.substring(fileName.lastIndexOf("."));
+        fileName = uploadDto.getFileMd5()+"_result" + suffix;
+        //合并文件
+        UploadChunk uploadChunk = uploadChunkService.getByFileMd5(uploadDto.getFileMd5());
+        if(uploadChunk == null){
+            throw new BusinessException(ResultCode.FILE_NOT_EXIST);
+        }
+        if(MinIoChunkUtils.composeObject(MinIoChunkUtils.chunkBucKet,chunks,fileName)){
+            //获取文件访问外链(1小时过期)
+            //String url = MinIoChunkUtils.getObjectUrl(MinIoChunkUtils.chunkBucKet,fileName,60);
+            String url = "/"+fileName;
+            //获取数据库里记录的文件信息,修改数据并返回文件信息
+            uploadChunkService.updateUrlByMd5(uploadDto.getFileMd5(),url);
+            uploadSceneService.updateStatusByUploadId(uploadChunk.getId(),1);
+            return ResultData.ok(uploadChunk);
+        }
+        uploadSceneService.updateStatusByUploadId(uploadChunk.getId(),-1);
+        throw new BusinessException(ResultCode.COMPOSE_FILE_ERROR);
+    }
 }

+ 46 - 0
src/main/java/com/fdkankan/fusion/controller/UploadSceneController.java

@@ -0,0 +1,46 @@
+package com.fdkankan.fusion.controller;
+
+
+import com.fdkankan.fusion.common.ResultCode;
+import com.fdkankan.fusion.common.ResultData;
+import com.fdkankan.fusion.entity.UploadScene;
+import com.fdkankan.fusion.exception.BusinessException;
+import com.fdkankan.fusion.request.UploadSceneParam;
+import com.fdkankan.fusion.service.IUploadSceneService;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.BeanUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * <p>
+ *  前端控制器
+ * </p>
+ *
+ * @author 
+ * @since 2024-12-17
+ */
+@RestController
+@RequestMapping("/uploadScene")
+public class UploadSceneController {
+
+
+    @Autowired
+    IUploadSceneService uploadSceneService;
+
+    @PostMapping("/add")
+    public ResultData add(@RequestBody UploadSceneParam param){
+        if(StringUtils.isBlank(param.getTitle()) || param.getType() == null || param.getUploadId() == null){
+            throw new BusinessException(ResultCode.MISSING_REQUIRED_PARAMETERS);
+        }
+        UploadScene uploadScene = new UploadScene();
+        BeanUtils.copyProperties(param,uploadScene);
+        uploadSceneService.save(uploadScene);
+        return ResultData.ok();
+    }
+}
+

+ 97 - 0
src/main/java/com/fdkankan/fusion/entity/UploadChunk.java

@@ -0,0 +1,97 @@
+package com.fdkankan.fusion.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import java.util.Date;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author 
+ * @since 2024-12-16
+ */
+@Getter
+@Setter
+@TableName("t_upload_chunk")
+public class UploadChunk implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    /**
+     * 云名称
+     */
+    @TableField("fyun_type")
+    private String fyunType;
+    /**
+     * bucket名称
+     */
+    @TableField("bucket_name")
+    private String bucketName;
+
+    /**
+     * 分片数量
+     */
+    @TableField("chunk_count")
+    private Integer chunkCount;
+
+    /**
+     * 文件md5
+     */
+    @TableField("file_md5")
+    private String fileMd5;
+
+    /**
+     * 文件名
+     */
+    @TableField("file_name")
+    private String fileName;
+
+    /**
+     * 文件大小
+     */
+    @TableField("file_size")
+    private String fileSize;
+
+    /**
+     * 后缀
+     */
+    @TableField("suffix")
+    private String suffix;
+
+    /**
+     * 文件路径
+     */
+    @TableField("file_path")
+    private String filePath;
+
+    /**
+     * 0上传中,1上传完成
+     */
+    @TableField("upload_status")
+    private Integer uploadStatus;
+
+    @TableField("tb_status")
+    @TableLogic
+    private Integer tbStatus;
+
+    @TableField("create_time")
+    private Date createTime;
+
+    @TableField("update_time")
+    private Date updateTime;
+
+
+
+
+}

+ 66 - 0
src/main/java/com/fdkankan/fusion/entity/UploadScene.java

@@ -0,0 +1,66 @@
+package com.fdkankan.fusion.entity;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableLogic;
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import java.util.Date;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * <p>
+ * 
+ * </p>
+ *
+ * @author 
+ * @since 2024-12-17
+ */
+@Getter
+@Setter
+@TableName("t_upload_scene")
+public class UploadScene implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    /**
+     * 标题
+     */
+    @TableField("title")
+    private String title;
+
+    /**
+     * 0法如e57 ,1法如e57加全景图,2标准e57,3AZ系列数据包
+     */
+    @TableField("type")
+    private Integer type;
+
+    /**
+     * 上传文件id
+     */
+    @TableField("upload_id")
+    private Integer uploadId;
+
+    @TableField("tm_user_id")
+    private Integer tmUserId;
+
+    @TableField("status")
+    private Integer status;
+
+    @TableField("tb_status")
+    @TableLogic
+    private Integer tbStatus;
+
+    @TableField("create_time")
+    private Date createTime;
+
+    @TableField("update_time")
+    private Date updateTime;
+
+
+}

+ 5 - 5
src/main/java/com/fdkankan/fusion/generate/AutoGenerate.java

@@ -18,7 +18,7 @@ public class AutoGenerate {
         String path =System.getProperty("user.dir") ;
 
         generate(path,"fusion", getTables(new String[]{
-               "mq_send_log"
+               "t_upload_scene"
         }));
 
 //        generate(path,"goods", getTables(new String[]{
@@ -46,10 +46,10 @@ public class AutoGenerate {
 
 
     public static void  generate(String path,String moduleName,  List<String> tables){
-//        FastAutoGenerator.create("jdbc:mysql://192.168.0.25:3306/fd_fusion_xj",
-//                "root","mysql123!ROOT.")
-        FastAutoGenerator.create("jdbc:mysql://120.24.144.164:3306/4dkankan_v4",
-                "root","4Dage@4Dage#@168")
+        FastAutoGenerator.create("jdbc:mysql://192.168.9.27:3306/fd_fusion_xj",
+                "root","mysql123!ROOT.")
+//        FastAutoGenerator.create("jdbc:mysql://120.24.144.164:3306/4dkankan_v4",
+//                "root","4Dage@4Dage#@168")
                 .globalConfig(builder -> {
                     builder.author("")               //作者
                             .outputDir(path+"\\src\\main\\java")    //输出路径(写到java目录)

+ 50 - 4
src/main/java/com/fdkankan/fusion/httpClient/FdService.java

@@ -8,18 +8,19 @@ import com.fdkankan.fusion.common.ResultData;
 import com.fdkankan.fusion.common.util.DateUtils;
 import com.fdkankan.fusion.common.util.RedisKeyUtil;
 import com.fdkankan.fusion.entity.TmCamera;
+import com.fdkankan.fusion.entity.UploadChunk;
+import com.fdkankan.fusion.entity.UploadScene;
 import com.fdkankan.fusion.exception.BusinessException;
 import com.fdkankan.fusion.httpClient.client.FdKKClient;
 import com.fdkankan.fusion.httpClient.client.LaserClient;
 import com.fdkankan.fusion.httpClient.client.TakeLookClient;
-import com.fdkankan.fusion.httpClient.request.FdRoomAddParam;
-import com.fdkankan.fusion.httpClient.request.FdkkCameraParam;
-import com.fdkankan.fusion.httpClient.request.FdkkDelNumParam;
-import com.fdkankan.fusion.httpClient.request.LaserSceneParam;
+import com.fdkankan.fusion.httpClient.request.*;
 import com.fdkankan.fusion.httpClient.response.FdRoomVo;
 import com.fdkankan.fusion.httpClient.response.FdkkLoginVo;
 import com.fdkankan.fusion.httpClient.response.FdkkResponse;
 import com.fdkankan.fusion.response.CameraVo;
+import com.fdkankan.fusion.service.IUploadChunkService;
+import com.fdkankan.fusion.service.IUploadSceneService;
 import com.fdkankan.redis.util.RedisUtil;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -59,6 +60,14 @@ public class FdService {
         }
         return vo.getFdToken();
     }
+    public Long getFdUserId(){
+        String jsObj = redisUtil.get(String.format(RedisKeyUtil.fusionLoginToken, StpUtil.getTokenValue()));
+        FdkkLoginVo vo = JSONObject.parseObject(jsObj, FdkkLoginVo.class);
+        if(vo == null){
+            throw new BusinessException(ResultCode.USER_NOT_LOGIN);
+        }
+        return vo.getUser().getId();
+    }
 
     public String getFdTokenByUserName(String userName) {
         return null;
@@ -135,4 +144,41 @@ public class FdService {
             throw new BusinessException(code,message);
         }
     }
+
+    @Autowired
+    IUploadChunkService uploadChunkService;
+    @Autowired
+    IUploadSceneService uploadSceneService;
+
+    public void toFdCreateScene(UploadScene uploadScene) {
+        UploadChunk uploadChunk = uploadChunkService.getById(uploadScene.getUploadId());
+        UploadEditSceneParam editSceneParam = new UploadEditSceneParam();
+        editSceneParam.setTitle(uploadScene.getTitle());
+        editSceneParam.setUserId(getFdUserId());
+        editSceneParam.setPath(uploadChunk.getFilePath());
+        editSceneParam.setBucket(uploadChunk.getBucketName());
+        editSceneParam.setFyunType(uploadChunk.getFyunType());
+        editSceneParam.setOtherType(toFdType(uploadScene.getType()));
+        try {
+            JSONObject jsonObject = fdKKClient.reverseScene(editSceneParam);
+            Integer code = jsonObject.getInteger("code");
+            if(code != 0){
+               uploadScene.setStatus(-2);
+            }
+        }catch (Exception e){
+            uploadScene.setStatus(-2);
+        }
+        uploadSceneService.updateById(uploadScene);
+    }
+
+    public String toFdType(Integer type){
+        switch (type){
+            case 0 :return "E57_V2";
+            case 1 :return "E57_V3";
+            case 2 :return "E57_V1";
+            case 3 :return "AZ";
+            default: throw new BusinessException(ResultCode.TYPE_ERROR);
+        }
+    }
+
 }

+ 3 - 4
src/main/java/com/fdkankan/fusion/httpClient/client/FdKKClient.java

@@ -4,10 +4,7 @@ import com.alibaba.fastjson.JSONObject;
 import com.dtflys.forest.annotation.*;
 import com.fdkankan.fusion.common.PageInfo;
 import com.fdkankan.fusion.httpClient.address.FdkkAddressSource;
-import com.fdkankan.fusion.httpClient.request.FdRoomAddParam;
-import com.fdkankan.fusion.httpClient.request.FdkkCameraParam;
-import com.fdkankan.fusion.httpClient.request.FdkkDelNumParam;
-import com.fdkankan.fusion.httpClient.request.FdkkLoginRequest;
+import com.fdkankan.fusion.httpClient.request.*;
 import com.fdkankan.fusion.httpClient.response.FdRoomVo;
 import com.fdkankan.fusion.httpClient.response.FdkkLoginVo;
 import com.fdkankan.fusion.httpClient.response.FdkkResponse;
@@ -110,4 +107,6 @@ public interface FdKKClient {
 
     @Get("/service/manage/inner/copyScene")
     JSONObject copyScene( @Query HashMap<String, Object> param ,@Header("sign") Long sign);
+    @Post("/api/scene/file/reverseScene")
+    JSONObject reverseScene( @JSONBody UploadEditSceneParam param);
 }

+ 19 - 0
src/main/java/com/fdkankan/fusion/httpClient/request/UploadEditSceneParam.java

@@ -0,0 +1,19 @@
+package com.fdkankan.fusion.httpClient.request;
+
+import lombok.Data;
+
+@Data
+public class UploadEditSceneParam {
+    /**
+     * {
+     *     "title":"测试AZ-1","userId":968,"otherType":"AZ","path":"reverseScene/original_auto3d-light-local-oZE6pxg53dYmDb02.zip"
+     * }
+     */
+
+    private String title;
+    private Long userId;
+    private String otherType;
+    private String path;
+    private String bucket;
+    private String fyunType;
+}

+ 18 - 0
src/main/java/com/fdkankan/fusion/mapper/IUploadChunkMapper.java

@@ -0,0 +1,18 @@
+package com.fdkankan.fusion.mapper;
+
+import com.fdkankan.fusion.entity.UploadChunk;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author 
+ * @since 2024-12-16
+ */
+@Mapper
+public interface IUploadChunkMapper extends BaseMapper<UploadChunk> {
+
+}

+ 18 - 0
src/main/java/com/fdkankan/fusion/mapper/IUploadSceneMapper.java

@@ -0,0 +1,18 @@
+package com.fdkankan.fusion.mapper;
+
+import com.fdkankan.fusion.entity.UploadScene;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * <p>
+ *  Mapper 接口
+ * </p>
+ *
+ * @author 
+ * @since 2024-12-17
+ */
+@Mapper
+public interface IUploadSceneMapper extends BaseMapper<UploadScene> {
+
+}

+ 10 - 0
src/main/java/com/fdkankan/fusion/request/UploadSceneParam.java

@@ -0,0 +1,10 @@
+package com.fdkankan.fusion.request;
+
+import lombok.Data;
+
+@Data
+public class UploadSceneParam {
+    private String title;
+    private Integer type;  //0法如e57 ,1法如e57加全景图,2标准e57,3AZ系列数据包
+    private Integer uploadId;
+}

+ 25 - 0
src/main/java/com/fdkankan/fusion/response/UploadChunkVo.java

@@ -0,0 +1,25 @@
+package com.fdkankan.fusion.response;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.fdkankan.fusion.entity.UploadChunk;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class UploadChunkVo extends UploadChunk {
+
+    /**
+     * 分片序号
+     */
+    @TableField(exist = false)
+    private String partNumber;
+
+    /**
+     * 上传地址
+     */
+    @TableField(exist = false)
+    private String uploadUrl;
+
+    private List<UploadChunkVo> uploadChunkVos;
+}

+ 19 - 0
src/main/java/com/fdkankan/fusion/service/IUploadChunkService.java

@@ -0,0 +1,19 @@
+package com.fdkankan.fusion.service;
+
+import com.fdkankan.fusion.entity.UploadChunk;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ *  服务类
+ * </p>
+ *
+ * @author 
+ * @since 2024-12-16
+ */
+public interface IUploadChunkService extends IService<UploadChunk> {
+
+    UploadChunk getByFileMd5(String fileMd5);
+
+    void updateUrlByMd5(String fileMd5, String url);
+}

+ 17 - 0
src/main/java/com/fdkankan/fusion/service/IUploadSceneService.java

@@ -0,0 +1,17 @@
+package com.fdkankan.fusion.service;
+
+import com.fdkankan.fusion.entity.UploadScene;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ * <p>
+ *  服务类
+ * </p>
+ *
+ * @author 
+ * @since 2024-12-17
+ */
+public interface IUploadSceneService extends IService<UploadScene> {
+
+    void updateStatusByUploadId(Integer uploadId, Integer status);
+}

+ 39 - 0
src/main/java/com/fdkankan/fusion/service/impl/UploadChunkServiceImpl.java

@@ -0,0 +1,39 @@
+package com.fdkankan.fusion.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.fdkankan.fusion.common.ResultCode;
+import com.fdkankan.fusion.entity.UploadChunk;
+import com.fdkankan.fusion.exception.BusinessException;
+import com.fdkankan.fusion.mapper.IUploadChunkMapper;
+import com.fdkankan.fusion.service.IUploadChunkService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ * <p>
+ *  服务实现类
+ * </p>
+ *
+ * @author 
+ * @since 2024-12-16
+ */
+@Service
+public class UploadChunkServiceImpl extends ServiceImpl<IUploadChunkMapper, UploadChunk> implements IUploadChunkService {
+
+    @Override
+    public UploadChunk getByFileMd5(String fileMd5) {
+        LambdaQueryWrapper<UploadChunk> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(UploadChunk::getFileMd5,fileMd5);
+        return this.getOne(wrapper);
+    }
+
+    @Override
+    public void updateUrlByMd5(String fileMd5, String url) {
+        LambdaUpdateWrapper<UploadChunk> wrapper = new LambdaUpdateWrapper<>();
+        wrapper.eq(UploadChunk::getFileMd5,fileMd5);
+        wrapper.set(UploadChunk::getFilePath,url);
+        wrapper.set(UploadChunk::getUploadStatus,1);
+        this.update(wrapper);
+    }
+}

+ 57 - 0
src/main/java/com/fdkankan/fusion/service/impl/UploadSceneServiceImpl.java

@@ -0,0 +1,57 @@
+package com.fdkankan.fusion.service.impl;
+
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
+import com.fdkankan.fusion.entity.UploadScene;
+import com.fdkankan.fusion.httpClient.FdService;
+import com.fdkankan.fusion.httpClient.client.FdKKClient;
+import com.fdkankan.fusion.httpClient.request.UploadEditSceneParam;
+import com.fdkankan.fusion.mapper.IUploadSceneMapper;
+import com.fdkankan.fusion.service.IUploadSceneService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * <p>
+ *  服务实现类
+ * </p>
+ *
+ * @author 
+ * @since 2024-12-17
+ */
+@Service
+public class UploadSceneServiceImpl extends ServiceImpl<IUploadSceneMapper, UploadScene> implements IUploadSceneService {
+
+    @Autowired
+    FdService fdService;
+    @Override
+    public void updateStatusByUploadId(Integer uploadId, Integer status) {
+
+        LambdaUpdateWrapper<UploadScene> wrapper = new LambdaUpdateWrapper<>();
+        wrapper.eq(UploadScene::getUploadId,uploadId);
+        wrapper.eq(UploadScene::getStatus,0);
+        wrapper.set(UploadScene::getStatus,status);
+        this.update(wrapper);
+
+        if(status == 1){
+            List<UploadScene> byUploadId = this.getByUploadId(uploadId);
+            if(!byUploadId.isEmpty()){
+                for (UploadScene uploadScene : byUploadId) {
+                    fdService.toFdCreateScene(uploadScene);
+                }
+            }
+        }
+    }
+
+    private List<UploadScene> getByUploadId(Integer uploadId) {
+        LambdaQueryWrapper<UploadScene> wrapper = new LambdaQueryWrapper<>();
+        wrapper.eq(UploadScene::getUploadId,uploadId);
+        wrapper.eq(UploadScene::getStatus,0);
+        return this.list(wrapper);
+    }
+
+
+}

+ 1 - 0
src/main/resources/application.yaml

@@ -124,5 +124,6 @@ minio:
   bucketName: laser-data                      # 存储桶bucket名称
   accessKey: Ux8mKEBFj4j2N63Kdj5g                         # 用户名
   secretKey: cPA5XSYcDzTCIHbeBxaSqzt9ZQjLZFbgQe38EiRW      # 密码
+  bucketChunk: fusion-chunk
 
 

+ 5 - 0
src/main/resources/mapper/fusion/UploadChunkMapper.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.fdkankan.fusion.mapper.IUploadChunkMapper">
+
+</mapper>

+ 5 - 0
src/main/resources/mapper/fusion/UploadSceneMapper.xml

@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.fdkankan.fusion.mapper.IUploadSceneMapper">
+
+</mapper>