浏览代码

Merge branch 'master' into project-local-jg

# Conflicts:
#	4dkankan-common-utils/src/main/java/com/fdkankan/common/constant/ErrorCode.java
dsx 2 年之前
父节点
当前提交
e7cf05245a
共有 31 个文件被更改,包括 1620 次插入38 次删除
  1. 2 0
      4dkankan-common-utils/src/main/java/com/fdkankan/common/constant/ErrorCode.java
  2. 2 1
      4dkankan-common-utils/src/main/java/com/fdkankan/common/constant/FileBizType.java
  3. 10 0
      4dkankan-common-web/src/main/java/com/fdkankan/web/annotation/NotResponseAdvice.java
  4. 7 0
      4dkankan-common-web/src/main/java/com/fdkankan/web/response/BaseResponseAdvice.java
  5. 28 0
      4dkankan-utils-fyun-cos/pom.xml
  6. 507 0
      4dkankan-utils-fyun-cos/src/main/java/com/fdkankan/fyun/oss/CosFileService.java
  7. 38 0
      4dkankan-utils-fyun-cos/src/main/java/com/fdkankan/fyun/oss/config/CosConfig.java
  8. 30 0
      4dkankan-utils-fyun-https/src/main/java/com/fdkankan/fyun/http/HttpFileService.java
  9. 30 0
      4dkankan-utils-fyun-local/src/main/java/com/fdkankan/fyun/local/LocalFileService.java
  10. 83 9
      4dkankan-utils-fyun-oss/src/main/java/com/fdkankan/fyun/oss/OssFileService.java
  11. 4 22
      4dkankan-utils-fyun-parent/src/main/java/com/fdkankan/fyun/config/FYunFileConfig.java
  12. 5 0
      4dkankan-utils-fyun-parent/src/main/java/com/fdkankan/fyun/face/AbstractFYunFileService.java
  13. 21 0
      4dkankan-utils-fyun-parent/src/main/java/com/fdkankan/fyun/face/FYunFileServiceInterface.java
  14. 107 4
      4dkankan-utils-fyun-s3/src/main/java/com/fdkankan/fyun/s3/S3FileService.java
  15. 2 2
      4dkankan-utils-mongodb/src/main/java/com/fdkankan/mongodb/base/BaseMongoEntity.java
  16. 5 0
      4dkankan-utils-redis/src/main/java/com/fdkankan/redis/constant/RedisKey.java
  17. 5 0
      4dkankan-utils-redis/src/main/java/com/fdkankan/redis/constant/RedisLockKey.java
  18. 60 0
      4dkankan-utils-redis/src/main/java/com/fdkankan/redis/util/RedissonLock.java
  19. 41 0
      4dkankan-utils-reg/pom.xml
  20. 39 0
      4dkankan-utils-reg/src/main/java/com/fdkankan/reg/CompressionUtil.java
  21. 114 0
      4dkankan-utils-reg/src/main/java/com/fdkankan/reg/Crypt.java
  22. 117 0
      4dkankan-utils-reg/src/main/java/com/fdkankan/reg/DeflaterUtil.java
  23. 21 0
      4dkankan-utils-reg/src/main/java/com/fdkankan/reg/EnvType.java
  24. 200 0
      4dkankan-utils-reg/src/main/java/com/fdkankan/reg/RegCodeUtil.java
  25. 17 0
      4dkankan-utils-reg/src/main/java/com/fdkankan/reg/dto/CamRegDto.java
  26. 18 0
      4dkankan-utils-reg/src/main/java/com/fdkankan/reg/dto/CamRegSDto.java
  27. 12 0
      4dkankan-utils-reg/src/main/java/com/fdkankan/reg/dto/MachineRegDto.java
  28. 7 0
      4dkankan-utils-rubber-sheeting/pom.xml
  29. 81 0
      4dkankan-utils-rubber-sheeting/src/main/java/com/fdkankan/rubbersheeting/TencentScalingService.java
  30. 5 0
      4dkankan-utils-sms/pom.xml
  31. 2 0
      pom.xml

+ 2 - 0
4dkankan-common-utils/src/main/java/com/fdkankan/common/constant/ErrorCode.java

@@ -163,6 +163,8 @@ public enum ErrorCode {
     FAILURE_CODE_5072(5072, "相机原始资源已被删除,不支持重算"),
     FAILURE_CODE_5072(5072, "相机原始资源已被删除,不支持重算"),
     FAILURE_CODE_5073(5073, "相机原始资源正在被清除"),
     FAILURE_CODE_5073(5073, "相机原始资源正在被清除"),
     FAILURE_CODE_5074(5074, "复制场景不支持重算"),
     FAILURE_CODE_5074(5074, "复制场景不支持重算"),
+    FAILURE_CODE_5075(5075, "模型不正确"),
+    FAILURE_CODE_5076(5076, "场景原始资源被冻结,不支持重算"),
 
 
     FAILURE_CODE_6003(6003, "该相机未被绑定,请前往 我的相机 先绑定相机后再进行授权 "),
     FAILURE_CODE_6003(6003, "该相机未被绑定,请前往 我的相机 先绑定相机后再进行授权 "),
 
 

+ 2 - 1
4dkankan-common-utils/src/main/java/com/fdkankan/common/constant/FileBizType.java

@@ -13,7 +13,8 @@ public enum FileBizType {
     TAG_ICON("tag-icon", "热点图标"),
     TAG_ICON("tag-icon", "热点图标"),
     LINK_STYLE("link-style", "场景关联图标"),
     LINK_STYLE("link-style", "场景关联图标"),
     WATERMARK("waterMark", "水印"),
     WATERMARK("waterMark", "水印"),
-    BOX_POSTER("box-poster", "空间视频封面图")
+    BOX_POSTER("box-poster", "空间视频封面图"),
+    BILLBOARD_ICON("billboard-icon", "指示牌")
     ;
     ;
 
 
     private String code;
     private String code;

+ 10 - 0
4dkankan-common-web/src/main/java/com/fdkankan/web/annotation/NotResponseAdvice.java

@@ -0,0 +1,10 @@
+package com.fdkankan.web.annotation;
+
+import java.lang.annotation.*;
+
+@Target({ElementType.PARAMETER, ElementType.METHOD})
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+public @interface NotResponseAdvice {
+    String description() default "";
+}

+ 7 - 0
4dkankan-common-web/src/main/java/com/fdkankan/web/response/BaseResponseAdvice.java

@@ -3,6 +3,7 @@ package com.fdkankan.web.response;
 
 
 import com.alibaba.fastjson.JSONObject;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.fdkankan.web.annotation.NotResponseAdvice;
 import lombok.extern.slf4j.Slf4j;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
 import org.springframework.core.MethodParameter;
 import org.springframework.core.MethodParameter;
@@ -13,12 +14,18 @@ import org.springframework.http.server.ServerHttpResponse;
 import org.springframework.web.bind.annotation.RestControllerAdvice;
 import org.springframework.web.bind.annotation.RestControllerAdvice;
 import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
 import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
 
 
+import java.util.Objects;
+
 @ConditionalOnMissingBean(name = "customResponseAdvice")
 @ConditionalOnMissingBean(name = "customResponseAdvice")
 @RestControllerAdvice
 @RestControllerAdvice
 @Slf4j
 @Slf4j
 public class BaseResponseAdvice implements ResponseBodyAdvice<Object> {
 public class BaseResponseAdvice implements ResponseBodyAdvice<Object> {
     @Override
     @Override
     public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
     public boolean supports(MethodParameter methodParameter, Class<? extends HttpMessageConverter<?>> aClass) {
+        NotResponseAdvice methodAnnotation = methodParameter.getMethodAnnotation(NotResponseAdvice.class);
+        if(Objects.nonNull(methodAnnotation)){
+            return false;
+        }
         return true;
         return true;
     }
     }
 
 

+ 28 - 0
4dkankan-utils-fyun-cos/pom.xml

@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <artifactId>4dkankan-utils</artifactId>
+        <groupId>com.fdkankan</groupId>
+        <version>3.0.0-SNAPSHOT</version>
+    </parent>
+    <artifactId>4dkankan-utils-fyun-cos</artifactId>
+    <properties>
+        <java.version>1.8</java.version>
+    </properties>
+    <dependencies>
+        <dependency>
+            <groupId>com.qcloud</groupId>
+            <artifactId>cos_api</artifactId>
+            <version>5.6.155</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.fdkankan</groupId>
+            <artifactId>4dkankan-utils-fyun-parent</artifactId>
+            <version>3.0.0-SNAPSHOT</version>
+        </dependency>
+    </dependencies>
+
+</project>

+ 507 - 0
4dkankan-utils-fyun-cos/src/main/java/com/fdkankan/fyun/oss/CosFileService.java

@@ -0,0 +1,507 @@
+package com.fdkankan.fyun.oss;
+
+import cn.hutool.core.collection.CollUtil;
+import cn.hutool.core.io.IoUtil;
+import com.alibaba.fastjson.JSON;
+import com.fdkankan.common.util.DateExtUtil;
+import com.fdkankan.fyun.constant.FYunTypeEnum;
+import com.fdkankan.fyun.face.AbstractFYunFileService;
+import com.qcloud.cos.COSClient;
+import com.qcloud.cos.ClientConfig;
+import com.qcloud.cos.auth.BasicCOSCredentials;
+import com.qcloud.cos.auth.COSCredentials;
+import com.qcloud.cos.http.HttpMethodName;
+import com.qcloud.cos.http.HttpProtocol;
+import com.qcloud.cos.model.*;
+import com.qcloud.cos.region.Region;
+import com.qcloud.cos.utils.IOUtils;
+import com.qcloud.cos.utils.Md5Utils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.stereotype.Component;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.ObjectUtils;
+import sun.misc.Cleaner;
+
+import java.io.*;
+import java.math.BigDecimal;
+import java.net.URL;
+import java.util.*;
+import java.util.stream.Collectors;
+
+@Component
+@ConditionalOnProperty(name = "fyun.type", havingValue = "cos")
+public class CosFileService extends AbstractFYunFileService {
+
+    private Logger log = LoggerFactory.getLogger(this.getClass().getName());
+
+    @Autowired
+    private COSClient cosClient;
+
+    public static COSClient getClient(){
+        // 1 初始化用户身份信息(secretId, secretKey)。
+        // SECRETID 和 SECRETKEY 请登录访问管理控制台 https://console.cloud.tencent.com/cam/capi 进行查看和管理
+        COSCredentials cred = new BasicCOSCredentials("AKIDlz42sV8sV3pW6UiiieXQuU0QrFbq9Qmx", "A8zmMoz1ufCYuCSmvxulV8hAXnx6EOTX");
+        // 2 设置 bucket 的地域, COS 地域的简称请参见 https://cloud.tencent.com/document/product/436/6224
+        // clientConfig 中包含了设置 region, https(默认 http), 超时, 代理等 set 方法, 使用可参见源码或者常见问题 Java SDK 部分。
+        Region region = new Region("ap-guangzhou");
+        ClientConfig clientConfig = new ClientConfig(region);
+        // 这里建议设置使用 https 协议
+        // 从 5.6.54 版本开始,默认使用了 https
+        clientConfig.setHttpProtocol(HttpProtocol.https);
+        // 3 生成 cos 客户端。
+        COSClient cosClient = new COSClient(cred, clientConfig);
+
+        return cosClient;
+    }
+
+    @Override
+    public String uploadFile(String bucket, byte[] data, String remoteFilePath) {
+        String contentMd5 = Md5Utils.md5AsBase64(data);
+        InputStream ins = new ByteArrayInputStream(data);
+        ObjectMetadata metadata = new ObjectMetadata();
+        metadata.setContentType("text/plain");
+        metadata.setContentLength(data.length);
+        metadata.setContentMD5(contentMd5);
+        cosClient.putObject(bucket, remoteFilePath, ins, metadata);
+        return null;
+    }
+
+    @Override
+    public String uploadFile(String bucket, String filePath, String remoteFilePath) {
+        return uploadFile(bucket, filePath, remoteFilePath, null);
+    }
+
+    @Override
+    public String uploadFile(String bucket, InputStream inputStream, String remoteFilePath) {
+        try {
+            cosClient.putObject(bucket, remoteFilePath, inputStream, new ObjectMetadata());
+            log.info("文件流上传成功,目标路径:remoteFilePath:{}", remoteFilePath);
+        } catch (Exception e) {
+            log.error("oss上传文件失败,remoteFilePath:"+remoteFilePath, e);
+        }
+        return null;
+    }
+
+    @Override
+    public String uploadFile(String bucket, String filePath, String remoteFilePath, Map<String, String> headers) {
+        File file = new File(filePath);
+        if (!file.exists()) {
+            log.warn("要上传的文件不存在,filePath" + filePath);
+            return null;
+        }
+        try (InputStream ins = new FileInputStream(file)){
+            ObjectMetadata metadata = new ObjectMetadata();
+            if (filePath.contains(".jpg")) {
+                metadata.setContentType("image/jpeg");
+            }
+            if (filePath.contains(".mp4")) {
+                metadata.setContentType("video/mp4");
+            }
+            if (filePath.contains(".mp3")) {
+                metadata.setContentType("audio/mp3");
+            }
+            if (org.apache.commons.lang3.ObjectUtils.isNotEmpty(headers)) {
+                for (Map.Entry<String, String> header : headers.entrySet()) {
+                    metadata.setHeader(header.getKey(), header.getValue());
+                }
+            }
+            cosClient.putObject(bucket, remoteFilePath, ins, metadata);
+            log.info("文件上传成功,path:{}", filePath);
+        } catch (Exception e) {
+            log.error("cos上传文件失败,filePath:"+filePath, e);
+        }
+        return null;
+    }
+
+    @Override
+    public String uploadFileByCommand(String bucket, String filePath, String remoteFilePath) {
+        try {
+            String optType = new File(filePath).isDirectory() ? "folder" : "file";
+            String command = String.format(fYunConstants.UPLOAD_SH, bucket, filePath, remoteFilePath, FYunTypeEnum.OSS.code(), optType);
+            log.info("开始上传文件, ossPath:{}, srcPath:{}", remoteFilePath, filePath);
+            callshell(command);
+            log.info("上传文件完毕, ossPath:{}, srcPath:{}", remoteFilePath, filePath);
+        } catch (Exception e) {
+            log.error(String.format("上传文件失败, ossPath:%s, srcPath:%s", remoteFilePath, filePath), e);
+        }
+        return null;
+    }
+
+    @Override
+    public void downloadFileByCommand(String bucket, String filePath, String remoteFilePath) {
+        try {
+            String optType = remoteFilePath.contains(".") ? "file" : "folder";
+            String command = String.format(fYunConstants.DOWNLOAD_SH, bucket, remoteFilePath, filePath, FYunTypeEnum.OSS.code(), optType);
+            log.info("开始下载文件, ossPath:{}, srcPath:{}", remoteFilePath, filePath);
+            callshell(command);
+            log.info("下载文件完毕, ossPath:{}, srcPath:{}", remoteFilePath, filePath);
+        } catch (Exception e) {
+            log.error(String.format("下载文件失败, ossPath:%s, srcPath:%s", remoteFilePath, filePath), e);
+        }
+    }
+
+    @Override
+    public void deleteFile(String bucket, String remoteFilePath) throws IOException {
+        try {
+            cosClient.deleteObject(bucket, remoteFilePath);
+        } catch (Exception e) {
+            log.error("OSS删除文件失败,key:" + remoteFilePath, e);
+        }
+    }
+
+    @Override
+    public void deleteFolder(String bucket, String remoteFolderPath) {
+        try {
+
+            if (!remoteFolderPath.endsWith("/")) {
+                remoteFolderPath = remoteFolderPath + "/";
+            }
+            log.info("开始删除文件夹:{}", remoteFolderPath);
+            boolean flag = true;
+            String nextMaker = null;
+            ListObjectsRequest listObjectsRequest = new ListObjectsRequest();
+            // 设置 bucket 名称
+            listObjectsRequest.setBucketName(bucket);
+            // prefix 表示列出的对象名以 prefix 为前缀
+            // 这里填要列出的目录的相对 bucket 的路径
+            listObjectsRequest.setPrefix(remoteFolderPath);
+            // 设置最大遍历出多少个对象, 一次 listobject 最大支持1000
+            listObjectsRequest.setMaxKeys(1000);
+
+
+            DeleteObjectsRequest request = new DeleteObjectsRequest(bucket);
+            do {
+                //获取下一页的起始点,它的下一项
+                ObjectListing objectListing = cosClient.listObjects(listObjectsRequest);
+                List<DeleteObjectsRequest.KeyVersion> keys = objectListing.getObjectSummaries().parallelStream()
+                        .map(cosObjectSummary -> new DeleteObjectsRequest.KeyVersion(cosObjectSummary.getKey())).collect(Collectors.toList());
+                if (!CollectionUtils.isEmpty(keys)) {
+                    request.setKeys(keys);
+                    cosClient.deleteObjects(request);
+                }
+                nextMaker = objectListing.getNextMarker();
+                listObjectsRequest.setMarker(nextMaker);
+                //全部执行完后,为false
+                flag = objectListing.isTruncated();
+            } while (flag);
+        } catch (Exception e) {
+            log.error("coss删除目录失败,key:" + remoteFolderPath, e);
+        }
+    }
+
+    @Override
+    public void uploadMulFiles(String bucket, Map<String, String> filepaths) {
+        try {
+            for (Map.Entry<String, String> entry : filepaths.entrySet()) {
+                uploadFile(bucket, entry.getKey(), entry.getValue(), null);
+            }
+        } catch (Exception e) {
+            log.error("OSS批量上传文件失败!");
+        }
+    }
+
+    @Override
+    public List<String> listRemoteFiles(String bucket, String sourcePath) {
+        List<String> keyList = new ArrayList<>();
+        try {
+            boolean flag = true;
+            String nextMaker = null;
+            ListObjectsRequest listObjectsRequest = new ListObjectsRequest();
+            listObjectsRequest.setBucketName(bucket);
+            //指定下一级文件
+            listObjectsRequest.setPrefix(sourcePath);
+            //设置分页的页容量
+            listObjectsRequest.setMaxKeys(1000);
+            do {
+                //获取下一页的起始点,它的下一项
+                ObjectListing objectListing = cosClient.listObjects(listObjectsRequest);
+                List<String> collect = objectListing.getObjectSummaries().parallelStream()
+                        .map(COSObjectSummary::getKey).filter(entity -> !entity.endsWith("/")).collect(Collectors.toList());
+                if (!CollectionUtils.isEmpty(collect)) {
+                    keyList.addAll(collect);
+                }
+                nextMaker = objectListing.getNextMarker();
+                listObjectsRequest.setMarker(nextMaker);
+                //全部执行完后,为false
+                flag = objectListing.isTruncated();
+            } while (flag);
+        } catch (Exception e) {
+            log.error("获取文件列表失败,path:" + sourcePath, e);
+        }
+        return keyList;
+    }
+
+    @Override
+    public void copyFileBetweenBucket(String sourceBucketName, String sourcePath, String targetBucketName, String targetPath) {
+        try {
+            List<String> files = listRemoteFiles(sourceBucketName, sourcePath);
+            if (ObjectUtils.isEmpty(files)) {
+                return;
+            }
+            files.stream().forEach(file -> {
+                cosClient.copyObject(sourceBucketName, file, targetBucketName, file.replace(sourcePath, targetPath));
+            });
+        } catch (Exception e) {
+            log.error("复制文件或目录失败,key:" + sourcePath, e);
+        }
+    }
+
+    @Override
+    public void copyFilesBetweenBucket(String sourceBucketName, String targetBucketName, Map<String, String> pathMap) {
+        if (ObjectUtils.isEmpty(pathMap)) {
+            return;
+        }
+        try {
+            for (Map.Entry<String, String> entry : pathMap.entrySet()) {
+                copyFileBetweenBucket(sourceBucketName, entry.getKey(), targetBucketName, entry.getValue());
+            }
+        } catch (Exception e) {
+            log.error(String.format("批量复制文件失败, sourceBucketName:%s, targetBucketName:%s", sourceBucketName, targetBucketName), e);
+        }
+    }
+
+    @Override
+    public String getFileContent(String bucketName, String remoteFilePath) {
+        try (COSObject object = cosClient.getObject(bucketName, remoteFilePath)){
+            InputStream objectContent = object.getObjectContent();
+            StringBuilder contentJson = new StringBuilder();
+            try (BufferedReader reader = new BufferedReader(new InputStreamReader(objectContent))) {
+                while (true) {
+                    String line = reader.readLine();
+                    if (line == null) break;
+                    contentJson.append(line);
+                }
+            } catch (IOException e) {
+                throw e;
+            }
+            return contentJson.toString();
+        } catch (Exception e) {
+            log.error("获取文件内容失败:key:"+remoteFilePath, e);
+        }
+        return null;
+    }
+
+    @Override
+    public boolean fileExist(String bucket, String key) {
+        try {
+            return cosClient.doesObjectExist(bucket, key);
+        } catch (Exception e) {
+            log.error("判断文件是否存在失败,key:"+key, e);
+        }
+        return false;
+    }
+
+    @Override
+    public void downloadFile(String bucket, String remoteFilePath, String localPath) {
+        try {
+            File localFile = new File(localPath);
+            if (!localFile.getParentFile().exists()) {
+                localFile.getParentFile().mkdirs();
+            }
+            if(localFile.isDirectory()){
+                String fileName = remoteFilePath.substring(remoteFilePath.lastIndexOf("/")+1);
+                log.info("未配置文件名,使用默认文件名:{}",fileName);
+                localPath = localPath.concat(File.separator).concat(fileName);
+            }
+
+            GetObjectRequest getObjectRequest = new GetObjectRequest(bucket, remoteFilePath);
+            cosClient.getObject(getObjectRequest, new File(localPath));
+        } catch (Throwable throwable) {
+            log.error("文件下载失败,key:"+remoteFilePath, throwable);
+        }
+    }
+
+    @Override
+    public URL getPresignedUrl(String bucket, String url) {
+        java.util.Date expiration = new java.util.Date();
+        long expTimeMillis = expiration.getTime();
+        expTimeMillis += 1000 * 60 * 60 * 8;
+        expiration.setTime(expTimeMillis);
+        GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest(bucket, url);
+        generatePresignedUrlRequest.setMethod(HttpMethodName.PUT);
+        generatePresignedUrlRequest.setExpiration(expiration);
+        return cosClient.generatePresignedUrl(generatePresignedUrlRequest);
+    }
+
+    @Override
+    public long getSubFileNums(String bucket, String url) {
+        long totalSubFileNum = 0;
+        try {
+            if (!url.endsWith("/")) {
+                url = url + "/";
+            }
+            boolean flag = true;
+            String nextMaker = null;
+            ListObjectsRequest listObjectsRequest = new ListObjectsRequest();
+            listObjectsRequest.setBucketName(bucket);
+            //指定下一级文件
+            listObjectsRequest.setPrefix(url);
+            //设置分页的页容量
+            listObjectsRequest.setMaxKeys(1000);
+            do {
+                //获取下一页的起始点,它的下一项
+                listObjectsRequest.setMarker(nextMaker);
+                ObjectListing objectListing = cosClient.listObjects(listObjectsRequest);
+                List<String> collect = objectListing.getObjectSummaries().parallelStream()
+                        .filter(summary -> !summary.getKey().endsWith("/")).map(COSObjectSummary::getKey).collect(Collectors.toList());
+                if (!CollectionUtils.isEmpty(collect)) {
+                    totalSubFileNum = totalSubFileNum + collect.size();
+                }
+                nextMaker = objectListing.getNextMarker();
+                //全部执行完后,为false
+                flag = objectListing.isTruncated();
+            } while (flag);
+        } catch (Exception e) {
+            log.error("获取文件数量失败,path:" + url, e);
+        }
+        return totalSubFileNum;
+    }
+
+    @Override
+    public Boolean checkStore(String bucket,String filePath){
+        ObjectMetadata objectMetadata =  cosClient.getObjectMetadata(bucket, filePath);
+        return !isRestoreCompleted(objectMetadata);
+    }
+
+    @Override
+    public void restoreFolder(String bucket,String folderName){
+        ObjectMetadata objectMetadata ;
+
+        List<String> objectList = this.listRemoteFiles(bucket, folderName);
+        if(CollUtil.isEmpty(objectList)){
+            return;
+        }
+        for (String objectName : objectList) {
+            objectMetadata =  cosClient.getObjectMetadata(bucket, objectName);
+            // 校验Object是否为归档类型Object。
+            StorageClass storageClass = objectMetadata.getStorageClassEnum();
+            if (storageClass == StorageClass.Archive) {
+                // 解冻Object。
+                cosClient.restoreObject(bucket, objectName,1);
+            }
+        }
+    }
+
+    private boolean isRestoreCompleted(ObjectMetadata objectMetadata){
+        Date restoreExpirationTime = objectMetadata.getRestoreExpirationTime();
+        if(Objects.nonNull(restoreExpirationTime) && restoreExpirationTime.after(Calendar.getInstance().getTime())){
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public Integer getRestoreFolderProcess(String bucket,String folderName){
+        ObjectMetadata objectMetadata ;
+
+        List<String> objectList = this.listRemoteFiles(bucket, folderName);
+        if(CollUtil.isEmpty(objectList)){
+            return 100;
+        }
+        List<String> restoreFileList = new ArrayList<>();
+        for (String objectName : objectList) {
+            objectMetadata = cosClient.getObjectMetadata(bucket, objectName);
+            if(this.isRestoreCompleted(objectMetadata)){
+
+                restoreFileList.add(objectName);
+            }
+        }
+        if(objectList.size() <= restoreFileList.size() ){
+            return 100;
+        }
+        BigDecimal rite = new BigDecimal(restoreFileList.size()).divide(new BigDecimal(objectList.size()),2,BigDecimal.ROUND_HALF_UP);
+        BigDecimal multiply = rite.multiply(new BigDecimal(100));
+        return multiply.intValue();
+    }
+
+    @Override
+    public void restoreFolder(String bucket, String folderName, Integer priority) {
+
+        List<String> objectList = this.listRemoteFiles(bucket, folderName);
+        if(CollUtil.isEmpty(objectList)){
+            return;
+        }
+        objectList.parallelStream().forEach(objectName -> {
+            this.restoreFile(bucket, objectName, priority);
+        });
+    }
+
+    @Override
+    public void restoreFile(String bucket, String objectName, Integer priority){
+        ObjectMetadata objectMetadata = cosClient.getObjectMetadata(bucket, objectName);
+        // 校验Object是否为归档类型Object。
+        StorageClass storageClass = objectMetadata.getStorageClassEnum();
+        if (storageClass == StorageClass.Archive) {
+            Tier tier = null;
+            switch (priority){
+                case 1 :
+                    tier = Tier.Expedited;
+                    break;
+                case 2 :
+                    tier = Tier.Standard;
+                    break;
+                case 3 :
+                    tier = Tier.Bulk;
+                    break;
+                default:
+                    tier = Tier.Standard;
+            }
+            // 设置 restore 得到的临时副本过期天数为1天
+            RestoreObjectRequest restoreObjectRequest = new RestoreObjectRequest(bucket, objectName, 1);
+            // 设置恢复模式为 Standard,其他的可选模式包括 Expedited 和 Bulk。若恢复归档存储类型数据,则支持上述三种恢复模式,选择不同恢复模式,在费用和恢复速度上不一样。若恢复深度归档存储类型数据,则仅支持 Standard 和 Bulk 恢复模式
+            CASJobParameters casJobParameters = new CASJobParameters();
+            casJobParameters.setTier(tier);
+            restoreObjectRequest.setCASJobParameters(casJobParameters);
+
+            //开始解冻
+            cosClient.restoreObject(restoreObjectRequest);
+        }
+    }
+
+    @Override
+    public Long getSpace(String bucket, String key) {
+
+        Long total = 0L;
+        boolean flag = true;
+        String nextMaker = null;
+        ListObjectsRequest listObjectsRequest = new ListObjectsRequest();
+        listObjectsRequest.setBucketName(bucket);
+        //指定下一级文件
+        listObjectsRequest.setPrefix(key);
+        //设置分页的页容量
+        listObjectsRequest.setMaxKeys(1000);
+        do {
+            //获取下一页的起始点,它的下一项
+            listObjectsRequest.setMarker(nextMaker);
+            ObjectListing objectListing = cosClient.listObjects(listObjectsRequest);
+            Long space = objectListing.getObjectSummaries().parallelStream()
+                    .mapToLong(COSObjectSummary::getSize).sum();
+            total += space;
+            nextMaker = objectListing.getNextMarker();
+            //全部执行完后,为false
+            flag = objectListing.isTruncated();
+        } while (flag);
+        return total;
+    }
+
+    @Override
+    public void copyFileToArchive(String sourceBucketName, String sourcePath, String targetBucketName, String targetPath) {
+        try {
+            List<String> files = listRemoteFiles(sourceBucketName, sourcePath);
+            if (ObjectUtils.isEmpty(files)) {
+                return;
+            }
+            files.stream().forEach(file -> {
+                CopyObjectRequest request = new CopyObjectRequest(sourceBucketName, file, targetBucketName, file.replace(sourcePath, targetPath));
+                request.setStorageClass(StorageClass.Archive);
+                cosClient.copyObject(request);
+            });
+        } catch (Exception e) {
+            log.error("复制文件或目录失败,key:" + sourcePath, e);
+        }
+    }
+
+}

+ 38 - 0
4dkankan-utils-fyun-cos/src/main/java/com/fdkankan/fyun/oss/config/CosConfig.java

@@ -0,0 +1,38 @@
+package com.fdkankan.fyun.oss.config;
+
+import com.fdkankan.fyun.config.FYunFileConfig;
+import com.qcloud.cos.COSClient;
+import com.qcloud.cos.ClientConfig;
+import com.qcloud.cos.auth.BasicCOSCredentials;
+import com.qcloud.cos.auth.COSCredentials;
+import com.qcloud.cos.http.HttpProtocol;
+import com.qcloud.cos.region.Region;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.context.annotation.Bean;
+import org.springframework.stereotype.Component;
+
+@Component
+@ConditionalOnProperty(name = "fyun.type", havingValue = "cos")
+public class CosConfig {
+
+    @Autowired
+    private FYunFileConfig fYunFileConfig;
+
+    @Bean
+    public COSClient cosClient(){
+        // 1 初始化用户身份信息(secretId, secretKey)。
+        // SECRETID 和 SECRETKEY 请登录访问管理控制台 https://console.cloud.tencent.com/cam/capi 进行查看和管理
+        COSCredentials cred = new BasicCOSCredentials(fYunFileConfig.getKey(), fYunFileConfig.getSecret());
+        // 2 设置 bucket 的地域, COS 地域的简称请参见 https://cloud.tencent.com/document/product/436/6224
+        // clientConfig 中包含了设置 region, https(默认 http), 超时, 代理等 set 方法, 使用可参见源码或者常见问题 Java SDK 部分。
+        Region region = new Region(fYunFileConfig.getRegion());
+        ClientConfig clientConfig = new ClientConfig(region);
+        // 这里建议设置使用 https 协议
+        // 从 5.6.54 版本开始,默认使用了 https
+        clientConfig.setHttpProtocol(HttpProtocol.https);
+        // 3 生成 cos 客户端。
+        COSClient cosClient = new COSClient(cred, clientConfig);
+        return cosClient;
+    }
+}

+ 30 - 0
4dkankan-utils-fyun-https/src/main/java/com/fdkankan/fyun/http/HttpFileService.java

@@ -311,4 +311,34 @@ public class HttpFileService extends AbstractFYunFileService {
         return 0;
         return 0;
     }
     }
 
 
+    @Override
+    public Boolean checkStore(String bucket, String url) {
+        return null;
+    }
+
+    @Override
+    public void restoreFolder(String bucket, String url) {
+
+    }
+
+    @Override
+    public Integer getRestoreFolderProcess(String bucket, String url) {
+        return null;
+    }
+
+    @Override
+    public void restoreFolder(String bucket, String folderName, Integer priority) {
+
+    }
+
+    @Override
+    public void restoreFile(String bucket, String objectName, Integer priority) {
+
+    }
+
+    @Override
+    public Long getSpace(String bucket, String key) {
+        return null;
+    }
+
 }
 }

+ 30 - 0
4dkankan-utils-fyun-local/src/main/java/com/fdkankan/fyun/local/LocalFileService.java

@@ -177,7 +177,37 @@ public class LocalFileService extends AbstractFYunFileService {
         return FileUtils.getSubFileNums(new File(getOssPath(bucket, url)));
         return FileUtils.getSubFileNums(new File(getOssPath(bucket, url)));
     }
     }
 
 
+    @Override
+    public void restoreFolder(String bucket, String folderName, Integer priority) {
+
+    }
+
+    @Override
+    public void restoreFile(String bucket, String objectName, Integer priority) {
+
+    }
+
     private String getOssPath(String bucket, String filePath) {
     private String getOssPath(String bucket, String filePath) {
         return LocalConstants.BASE_PATH.concat(bucket).concat(File.separator).concat(filePath);
         return LocalConstants.BASE_PATH.concat(bucket).concat(File.separator).concat(filePath);
     }
     }
+
+    @Override
+    public Boolean checkStore(String bucket, String url) {
+        return null;
+    }
+
+    @Override
+    public void restoreFolder(String bucket, String url) {
+
+    }
+
+    @Override
+    public Integer getRestoreFolderProcess(String bucket, String url) {
+        return null;
+    }
+
+    @Override
+    public Long getSpace(String bucket, String key) {
+        return null;
+    }
 }
 }

+ 83 - 9
4dkankan-utils-fyun-oss/src/main/java/com/fdkankan/fyun/oss/OssFileService.java

@@ -13,8 +13,10 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.stereotype.Component;
 import org.springframework.stereotype.Component;
 import org.springframework.util.CollectionUtils;
 import org.springframework.util.CollectionUtils;
 import org.springframework.util.ObjectUtils;
 import org.springframework.util.ObjectUtils;
+import org.springframework.util.StringUtils;
 
 
 import java.io.*;
 import java.io.*;
+import java.math.BigDecimal;
 import java.net.URL;
 import java.net.URL;
 import java.util.ArrayList;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.List;
@@ -323,6 +325,54 @@ public class OssFileService extends AbstractFYunFileService {
     }
     }
 
 
     @Override
     @Override
+    public Boolean checkStore(String bucket,String filePath){
+        ObjectMetadata objectMetadata =  ossClient.getObjectMetadata(bucket, filePath);
+        return !objectMetadata.isRestoreCompleted();
+    }
+
+    @Override
+    public void restoreFolder(String bucket,String folderName){
+        ObjectMetadata objectMetadata ;
+
+        List<String> objectList = this.listRemoteFiles(bucket, folderName);
+        if(CollUtil.isEmpty(objectList)){
+            return;
+        }
+        for (String objectName : objectList) {
+            objectMetadata =  ossClient.getObjectMetadata(bucket, objectName);
+            // 校验Object是否为归档类型Object。
+            StorageClass storageClass = objectMetadata.getObjectStorageClass();
+            if (storageClass == StorageClass.ColdArchive) {
+                // 解冻Object。
+                ossClient.restoreObject(bucket, objectName);
+            }
+        }
+    }
+
+    @Override
+    public Integer getRestoreFolderProcess(String bucket,String folderName){
+        ObjectMetadata objectMetadata ;
+
+        List<String> objectList = this.listRemoteFiles(bucket, folderName);
+        if(CollUtil.isEmpty(objectList)){
+            return 100;
+        }
+        List<String> restoreFileList = new ArrayList<>();
+        for (String objectName : objectList) {
+            objectMetadata = ossClient.getObjectMetadata(bucket, objectName);
+            if(objectMetadata.isRestoreCompleted()){
+                restoreFileList.add(objectName);
+            }
+        }
+        if(objectList.size() <= restoreFileList.size() ){
+            return 100;
+        }
+        BigDecimal rite = new BigDecimal(restoreFileList.size()).divide(new BigDecimal(objectList.size()),2,BigDecimal.ROUND_HALF_UP);
+        BigDecimal multiply = rite.multiply(new BigDecimal(100));
+        return multiply.intValue();
+    }
+
+    @Override
     public void restoreFolder(String bucket, String folderName, Integer priority) {
     public void restoreFolder(String bucket, String folderName, Integer priority) {
 
 
         List<String> objectList = this.listRemoteFiles(bucket, folderName);
         List<String> objectList = this.listRemoteFiles(bucket, folderName);
@@ -363,17 +413,41 @@ public class OssFileService extends AbstractFYunFileService {
             RestoreConfiguration configuration = new RestoreConfiguration(1, jobParameters);
             RestoreConfiguration configuration = new RestoreConfiguration(1, jobParameters);
             //开始解冻
             //开始解冻
             ossClient.restoreObject(bucket, objectName, configuration);
             ossClient.restoreObject(bucket, objectName, configuration);
-            // 等待解冻完成。
-            do {
-                try {
-                    Thread.sleep(1000);
-                } catch (InterruptedException e) {
-                    e.printStackTrace();
-                }
-                objectMetadata = ossClient.getObjectMetadata(bucket, objectName);
-            } while (!objectMetadata.isRestoreCompleted());
+//            // 等待解冻完成。
+//            do {
+//                try {
+//                    Thread.sleep(1000);
+//                } catch (InterruptedException e) {
+//                    e.printStackTrace();
+//                }
+//                objectMetadata = ossClient.getObjectMetadata(bucket, objectName);
+//            } while (!objectMetadata.isRestoreCompleted());
         }
         }
     }
     }
 
 
+    @Override
+    public Long getSpace(String bucket, String key) {
+
+        Long total = 0L;
+        boolean flag = true;
+        String nextMaker = null;
+        ListObjectsRequest listObjectsRequest = new ListObjectsRequest(bucket);
+        //指定下一级文件
+        listObjectsRequest.setPrefix(key);
+        //设置分页的页容量
+        listObjectsRequest.setMaxKeys(200);
+        do {
+            //获取下一页的起始点,它的下一项
+            listObjectsRequest.setMarker(nextMaker);
+            ObjectListing objectListing = ossClient.listObjects(listObjectsRequest);
+            Long space = objectListing.getObjectSummaries().parallelStream()
+                    .mapToLong(OSSObjectSummary::getSize).sum();
+            total += space;
+            nextMaker = objectListing.getNextMarker();
+            //全部执行完后,为false
+            flag = objectListing.isTruncated();
+        } while (flag);
+        return total;
+    }
 
 
 }
 }

+ 4 - 22
4dkankan-utils-fyun-parent/src/main/java/com/fdkankan/fyun/config/FYunFileConfig.java

@@ -1,8 +1,10 @@
 package com.fdkankan.fyun.config;
 package com.fdkankan.fyun.config;
 
 
+import lombok.Data;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Component;
 import org.springframework.stereotype.Component;
 
 
+@Data
 @Component
 @Component
 public class FYunFileConfig {
 public class FYunFileConfig {
 
 
@@ -27,27 +29,7 @@ public class FYunFileConfig {
     @Value("${fyun.host}")
     @Value("${fyun.host}")
     private String host;
     private String host;
 
 
-    public String getKey() {
-        return key;
-    }
+    @Value("${fyun.region:#{null}}")
+    private String region;
 
 
-    public String getSecret() {
-        return secret;
-    }
-
-    public String getBucket() {
-        return bucket;
-    }
-
-    public String getEndPoint() {
-        return endPoint;
-    }
-
-    public String getFyunType() {
-        return fyunType;
-    }
-
-    public String getHost() {
-        return host;
-    }
 }
 }

+ 5 - 0
4dkankan-utils-fyun-parent/src/main/java/com/fdkankan/fyun/face/AbstractFYunFileService.java

@@ -87,6 +87,11 @@ public abstract class AbstractFYunFileService implements FYunFileServiceInterfac
         copyFileBetweenBucket(fYunFileConfig.getBucket(), sourcePath, fYunFileConfig.getBucket(), targetPath);
         copyFileBetweenBucket(fYunFileConfig.getBucket(), sourcePath, fYunFileConfig.getBucket(), targetPath);
     }
     }
 
 
+    @Override
+    public void copyFileToArchive(String sourceBucketName, String sourcePath, String targetBucketName, String targetPath) {
+        copyFileToArchive(sourceBucketName, sourcePath, targetBucketName, targetPath);
+    }
+
     public void copyFileInBucket(String bucket, String sourcePath, String targetPath) {
     public void copyFileInBucket(String bucket, String sourcePath, String targetPath) {
         copyFileBetweenBucket(bucket, sourcePath, bucket, targetPath);
         copyFileBetweenBucket(bucket, sourcePath, bucket, targetPath);
     }
     }

+ 21 - 0
4dkankan-utils-fyun-parent/src/main/java/com/fdkankan/fyun/face/FYunFileServiceInterface.java

@@ -233,6 +233,18 @@ public interface FYunFileServiceInterface {
 
 
     /**
     /**
      * <p>
      * <p>
+     * 拷贝目录
+     * </p>
+     *
+     * @param sourcePath
+     * @param targetPath
+     * @author dengsixing
+     * @date 2022/1/18
+     **/
+    void copyFileToArchive(String sourceBucketName, String sourcePath, String targetBucketName, String targetPath) ;
+
+    /**
+     * <p>
      * 拷贝系统bucket目录至指定bucket
      * 拷贝系统bucket目录至指定bucket
      * </p>
      * </p>
      *
      *
@@ -268,6 +280,7 @@ public interface FYunFileServiceInterface {
     void copyFilesBetweenBucket(String targetBucketName, Map<String, String> pathMap) ;
     void copyFilesBetweenBucket(String targetBucketName, Map<String, String> pathMap) ;
 
 
 
 
+
     /**
     /**
      * 获取文件内容,文件内容过大时,会有造成内存溢出的风险,慎用
      * 获取文件内容,文件内容过大时,会有造成内存溢出的风险,慎用
      *
      *
@@ -329,7 +342,15 @@ public interface FYunFileServiceInterface {
 
 
     public long getSubFileNums(String bucket,String url);
     public long getSubFileNums(String bucket,String url);
 
 
+    public Boolean checkStore(String bucket,String url);
+
+    public void restoreFolder(String bucket,String url);
+
+    public Integer getRestoreFolderProcess(String bucket,String url);
+
     public void restoreFolder(String bucket, String folderName, Integer priority);
     public void restoreFolder(String bucket, String folderName, Integer priority);
 
 
     public void restoreFile(String bucket, String objectName, Integer priority);
     public void restoreFile(String bucket, String objectName, Integer priority);
+
+    public Long getSpace(String bucket, String key);
 }
 }

+ 107 - 4
4dkankan-utils-fyun-s3/src/main/java/com/fdkankan/fyun/s3/S3FileService.java

@@ -16,9 +16,7 @@ import org.springframework.util.ObjectUtils;
 
 
 import java.io.*;
 import java.io.*;
 import java.net.URL;
 import java.net.URL;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 import java.util.stream.Collectors;
 import java.util.stream.Collectors;
 
 
 @Component
 @Component
@@ -334,11 +332,116 @@ public class S3FileService extends AbstractFYunFileService {
 
 
     @Override
     @Override
     public void restoreFolder(String bucket, String folderName, Integer priority) {
     public void restoreFolder(String bucket, String folderName, Integer priority) {
-
+        List<String> objectList = this.listRemoteFiles(bucket, folderName);
+        if(CollUtil.isEmpty(objectList)){
+            return;
+        }
+        objectList.parallelStream().forEach(objectName -> {
+            this.restoreFile(bucket, objectName, priority);
+        });
     }
     }
 
 
     @Override
     @Override
     public void restoreFile(String bucket, String objectName, Integer priority){
     public void restoreFile(String bucket, String objectName, Integer priority){
+//        ObjectMetadata objectMetadata = ossClient.getObjectMetadata(bucket, objectName);
+//
+//        // 校验Object是否为归档类型Object。
+//        StorageClass storageClass = objectMetadata.getObjectStorageClass();
+//        if (storageClass == StorageClass.ColdArchive) {
+//            // 设置解冻冷归档Object的优先级。
+//            // RestoreTier.RESTORE_TIER_EXPEDITED 表示1小时内完成解冻。
+//            // RestoreTier.RESTORE_TIER_STANDARD 表示2~5小时内完成解冻。
+//            // RestoreTier.RESTORE_TIER_BULK 表示5~12小时内完成解冻。
+//            RestoreTier restoreTier = null;
+//            switch (priority){
+//                case 1 :
+//                    restoreTier = RestoreTier.RESTORE_TIER_EXPEDITED;
+//                    break;
+//                case 2 :
+//                    restoreTier = RestoreTier.RESTORE_TIER_STANDARD;
+//                    break;
+//                default:
+//                    restoreTier = RestoreTier.RESTORE_TIER_BULK;
+//            }
+//            RestoreJobParameters jobParameters = new RestoreJobParameters(restoreTier);
+//            // 配置解冻参数,以设置5小时内解冻完成,解冻状态保持2天为例。
+//            // 第一个参数表示保持解冻状态的天数,默认是1天,此参数适用于解冻Archive(归档)与ColdArchive(冷归档)类型Object。
+//            // 第二个参数jobParameters表示解冻优先级,只适用于解冻ColdArchive类型Object。
+//            RestoreConfiguration configuration = new RestoreConfiguration(1, jobParameters);
+//            //开始解冻
+//            ossClient.restoreObject(bucket, objectName, configuration);
+////            // 等待解冻完成。
+////            do {
+////                try {
+////                    Thread.sleep(1000);
+////                } catch (InterruptedException e) {
+////                    e.printStackTrace();
+////                }
+////                objectMetadata = ossClient.getObjectMetadata(bucket, objectName);
+////            } while (!objectMetadata.isRestoreCompleted());
+//        }
+    }
+
+    @Override
+    public Boolean checkStore(String bucket, String url) {
+        ObjectMetadata objectMetadata =  s3.getObjectMetadata(bucket, url);
+        return !isRestoreCompleted(objectMetadata);
+    }
+
+    private boolean isRestoreCompleted(ObjectMetadata objectMetadata){
+        Date restoreExpirationTime = objectMetadata.getRestoreExpirationTime();
+        if(Objects.nonNull(restoreExpirationTime) && restoreExpirationTime.after(Calendar.getInstance().getTime())){
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public void restoreFolder(String bucket, String url) {
+        ObjectMetadata objectMetadata ;
 
 
+        List<String> objectList = this.listRemoteFiles(bucket, url);
+        if(CollUtil.isEmpty(objectList)){
+            return;
+        }
+        for (String objectName : objectList) {
+            objectMetadata = s3.getObjectMetadata(bucket, objectName);
+            // 校验Object是否为归档类型Object。
+            StorageClass storageClass = objectMetadata.getArchiveStatus();
+            if (storageClass == StorageClass.) {
+                // 解冻Object。
+                RestoreObjectRequest requestRestore = new RestoreObjectRequest(bucket, url, 1);
+                s3.restoreObjectV2(requestRestore);
+            }
+        }
+    }
+
+    @Override
+    public Integer getRestoreFolderProcess(String bucket, String url) {
+        return null;
+    }
+
+    @Override
+    public Long getSpace(String bucket, String key) {
+        List<String> keyList = new ArrayList<>();
+        Long total = 0L;
+        boolean flag = true;
+        String nextMaker = null;
+        ListObjectsRequest listObjectsRequest = new ListObjectsRequest();
+        listObjectsRequest.setBucketName(bucket);
+        listObjectsRequest.setPrefix(key);
+        listObjectsRequest.setMaxKeys(200);
+
+        do {
+            listObjectsRequest.setMarker(nextMaker);
+            ObjectListing objectListing = s3.listObjects(listObjectsRequest);
+            List<S3ObjectSummary> objectSummaries = objectListing.getObjectSummaries();
+            Long space = objectSummaries.stream().mapToLong(S3ObjectSummary::getSize).sum();
+            total += space;
+            nextMaker = objectListing.getNextMarker();
+            flag = objectListing.isTruncated();
+        } while (flag);
+
+        return total;
     }
     }
 }
 }

+ 2 - 2
4dkankan-utils-mongodb/src/main/java/com/fdkankan/mongodb/base/BaseMongoEntity.java

@@ -17,11 +17,11 @@ public class BaseMongoEntity {
 
 
    private String id;
    private String id;
 
 
-   @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
+   @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @Field("createTime")
    @Field("createTime")
    private Date createTime;
    private Date createTime;
 
 
-   @JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
+   @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private Date updateTime;
    private Date updateTime;
 
 
    /**
    /**

+ 5 - 0
4dkankan-utils-redis/src/main/java/com/fdkankan/redis/constant/RedisKey.java

@@ -120,6 +120,11 @@ public class RedisKey {
     public static final String SCENE_LINKPAN_STYLES = "scene:LinkPanStyles:num:%s";
     public static final String SCENE_LINKPAN_STYLES = "scene:LinkPanStyles:num:%s";
 
 
     /**
     /**
+     * 场景关联styles数据列表
+     */
+    public static final String SCENE_BILLBOARDS_STYLES = "scene:billboardsStyles:num:%s";
+
+    /**
      * 场景指示牌数据列表
      * 场景指示牌数据列表
      */
      */
     public static final String SCENE_BILLBOARDS = "scene:billboards:num:%s";
     public static final String SCENE_BILLBOARDS = "scene:billboards:num:%s";

+ 5 - 0
4dkankan-utils-redis/src/main/java/com/fdkankan/redis/constant/RedisLockKey.java

@@ -90,6 +90,11 @@ public class RedisLockKey {
     public static String LOCK_LINKPAN_STYLES_SYNC = "lock:linkpan:styles:sync:num:%s";
     public static String LOCK_LINKPAN_STYLES_SYNC = "lock:linkpan:styles:sync:num:%s";
 
 
     /**
     /**
+     * 场景关联styles数据恢复锁
+     */
+    public static String LOCK_BILLBOARDS_STYLES_SYNC = "lock:Billboards:styles:sync:num:%s";
+
+    /**
      * 场景指示牌数据恢复锁
      * 场景指示牌数据恢复锁
      */
      */
     public static String LOCK_BILLBOARDS_SYNC = "lock:billboards:sync:num:%s";
     public static String LOCK_BILLBOARDS_SYNC = "lock:billboards:sync:num:%s";

+ 60 - 0
4dkankan-utils-redis/src/main/java/com/fdkankan/redis/util/RedissonLock.java

@@ -0,0 +1,60 @@
+package com.fdkankan.redis.util;
+
+import lombok.extern.slf4j.Slf4j;
+import org.redisson.api.RLock;
+import org.redisson.api.RedissonClient;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * 分布式Redis锁
+ */
+@Slf4j
+@Component
+public class RedissonLock {
+
+    @Autowired
+    private RedissonClient redissonClient;
+
+    // 加锁
+    public Boolean lock(String lockName) {
+        if (redissonClient == null) {
+            log.info("DistributedRedisLock redissonClient is null");
+            return false;
+        }
+
+        try {
+            RLock lock = redissonClient.getLock(lockName);
+            // 锁15秒后自动释放,防止死锁
+            lock.lock(15, TimeUnit.SECONDS);
+
+            log.info("Thread [{}] DistributedRedisLock lock [{}] success", Thread.currentThread().getName(), lockName);
+            // 加锁成功
+            return true;
+        } catch (Exception e) {
+            log.error("DistributedRedisLock lock [{}] Exception:", lockName, e);
+            return false;
+        }
+    }
+
+    // 释放锁
+    public Boolean unlock(String lockName) {
+        if (redissonClient == null) {
+            log.info("DistributedRedisLock redissonClient is null");
+            return false;
+        }
+
+        try {
+            RLock lock = redissonClient.getLock(lockName);
+            lock.unlock();
+            log.info("Thread [{}] DistributedRedisLock unlock [{}] success", Thread.currentThread().getName(), lockName);
+            // 释放锁成功
+            return true;
+        } catch (Exception e) {
+            log.error("DistributedRedisLock unlock [{}] Exception:", lockName, e);
+            return false;
+        }
+    }
+}

+ 41 - 0
4dkankan-utils-reg/pom.xml

@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>4dkankan-utils</artifactId>
+        <groupId>com.fdkankan</groupId>
+        <version>3.0.0-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>4dkankan-utils-reg</artifactId>
+
+    <properties>
+        <fastjson.version>2.0.6</fastjson.version>
+        <hutool.version>5.8.6</hutool.version>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>ch.qos.logback</groupId>
+            <artifactId>logback-classic</artifactId>
+            <version>1.2.11</version>
+        </dependency>
+        <!-- 阿里JSON解析器 -->
+        <dependency>
+            <groupId>com.alibaba.fastjson2</groupId>
+            <artifactId>fastjson2</artifactId>
+            <version>${fastjson.version}</version>
+        </dependency>
+
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-all</artifactId>
+            <version>${hutool.version}</version>
+        </dependency>
+
+
+    </dependencies>
+
+</project>

+ 39 - 0
4dkankan-utils-reg/src/main/java/com/fdkankan/reg/CompressionUtil.java

@@ -0,0 +1,39 @@
+package com.fdkankan.reg;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Base64;
+import java.util.zip.GZIPInputStream;
+import java.util.zip.GZIPOutputStream;
+/**
+ * CompressionUtil 压缩字符串
+ */
+public class CompressionUtil {
+
+    public static String compressAndEncode(String data) throws IOException {
+        byte[] input = data.getBytes("UTF-8");
+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+        GZIPOutputStream gzipOutputStream = new GZIPOutputStream(outputStream);
+        gzipOutputStream.write(input);
+        gzipOutputStream.close();
+        byte[] compressed = outputStream.toByteArray();
+        byte[] encoded = Base64.getEncoder().encode(compressed);
+        return new String(encoded, "UTF-8");
+    }
+
+    public static String decodeAndDecompress(String encodedData) throws IOException {
+        byte[] encoded = encodedData.getBytes("UTF-8");
+        byte[] compressed = Base64.getDecoder().decode(encoded);
+        ByteArrayInputStream inputStream = new ByteArrayInputStream(compressed);
+        GZIPInputStream gzipInputStream = new GZIPInputStream(inputStream);
+        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+        byte[] buffer = new byte[1024];
+        int length;
+        while ((length = gzipInputStream.read(buffer)) > 0) {
+            outputStream.write(buffer, 0, length);
+        }
+        gzipInputStream.close();
+        return new String(outputStream.toByteArray(), "UTF-8");
+    }
+}

+ 114 - 0
4dkankan-utils-reg/src/main/java/com/fdkankan/reg/Crypt.java

@@ -0,0 +1,114 @@
+package com.fdkankan.reg;
+
+import javax.crypto.Cipher;
+import javax.crypto.SecretKey;
+import javax.crypto.spec.SecretKeySpec;
+import java.util.Base64;
+/***
+* @description:激光相机本地版加密解密SNcode配合laserGen项目使用
+* @author: Xiewj
+* @date: 2023/6/14 18:19
+* @param:
+* @return:
+**/
+public class Crypt {
+   private static String key = "4dage1684dage168";
+
+
+   //用于构建十六进制输出
+   private static final char[] DIGITS_LOWER = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
+
+   /**
+    * AES解密 128 AES/ECB/PKCS5Padding
+    *
+    * @param source      需要解密的字符串
+    * @param hexOrBase64 true:hex,false:base64
+    * @return 返回解密结果
+    */
+   public static String decryptAES(String source, boolean hexOrBase64) {
+      try {
+         SecretKey secretKey = new SecretKeySpec(key.getBytes(), "AES");
+         Cipher cipher = Cipher.getInstance("AES");
+         cipher.init(Cipher.DECRYPT_MODE, secretKey);
+         if (hexOrBase64) {
+            return new String(cipher.doFinal (hex2bytes(source))).toUpperCase();
+         } else {
+            return new String(cipher.doFinal( decodeBase64(source))).toUpperCase();
+         }
+      } catch (Exception e) {
+         System.out.println(e.getMessage());
+         throw new RuntimeException("出错啦!", e);
+      }
+   }
+   /**
+    * AES加密 128 AES/ECB/PKCS5Padding
+    *
+    * @param source      需要加密的字符串
+    * @param hexOrBase64 true:hex,false:base64
+    * @return 返回加密结果
+    */
+   public static String encryptAES(String source,   boolean hexOrBase64) {
+      try {
+         SecretKey secretKey = new SecretKeySpec(key.getBytes(), "AES");
+         Cipher cipher = Cipher.getInstance("AES");
+         cipher.init(Cipher.ENCRYPT_MODE, secretKey);
+         if (hexOrBase64) {
+            return new String( bytes2hex(cipher.doFinal(source.getBytes()))).toUpperCase();
+         } else {
+            return  encodeBase64(cipher.doFinal(source.getBytes())).toUpperCase();
+         }
+      } catch (Exception e) {
+         throw new RuntimeException("出错啦!", e);
+      }
+
+   }
+
+   public static byte[] hex2bytes(String hexStr) {
+      byte[] bytes = new byte[hexStr.length() / 2];
+      for (int i = 0; i < hexStr.length(); i += 2) {
+         bytes[i / 2] = (byte) ((Character.digit(hexStr.charAt(i), 16) << 4)
+                 + Character.digit(hexStr.charAt(i+1), 16));
+      }
+      return bytes;
+   }
+
+
+   public static byte[] decodeBase64(String text) {
+      return java.util.Base64.getDecoder().decode(text);
+   }
+
+
+   public static char[] bytes2hex(final byte[] data) {
+      final int l = data.length;
+      final char[] out = new char[l << 1];
+      // two characters form the hex value.
+      for (int i = 0, j = 0; i < l; i++) {
+         out[j++] = DIGITS_LOWER[(0xF0 & data[i]) >>> 4];
+         out[j++] = DIGITS_LOWER[0x0F & data[i]];
+      }
+      return out;
+   }
+
+
+   public static String encodeBase64(byte[] data) {
+      return Base64.getEncoder().encodeToString(data);
+   }
+
+
+
+   public static void main(String[] args) throws Exception {
+      String value ="A5C140AB33E4F6F1BA6B675875A424BB22BF15DD6DE1A4A5933F627B89BFADCA033FBF152BB9966B8489EDD346201562";
+      //"HmtaYAN+n8dzKifi50/sA4Sv/dLKR5MnfZKcJVSzmST0D7ZkbmM8AebuNNkKBc4Z7DoXDnDwwwap2hg+6ztWQAZdQZOfAHR5bueqpApDN9il6gIuQadcdPcvrurRRiTifOQYsE9nRQKy6smol0jrz0wLEDxyPh3ZfBZG0e5KxrEq6Es6E3/05F4jIBYy+dUtvYBPSrVi3kzkblFex6qZOf/6jbtSlchWJVXMuEgA05LplUlUvNr5vwNC65KIy6beHcyhntIO2wJHx5uknjtidXUft3s87ZlxTzMEiKV6cXU9ejuCxdOz9n0c7UPeAOqHprxW2FvOhytVSMoSPP6No9pSochmKdXBPgOQd15rswBi0ejSZ+qWG4/MrBhVFD5OaQ8Cr7wy9hoWdnYrd0tcxPZv4EiwF3DDqctffYgQjy8=";
+      //"openid=ouQdHv18KY5HPhW16cDk43Y5-yyk&nickname=%e6%9d%8e%e5%a8%81&headimg=http%3a%2f%2fthirdwx.qlogo.cn%2fmmopen%2fajNVdqHZLLB6qkUjQibrUJniaBhLf8hjS5L4roMR84T62m7NyHiaIAXKh1cl2vJwfdSfEzju8HicugEXbJQFHx1pZw%2f132&rytype=1&nwflag=1&empno=BEJY3293&stime=1603340863000";
+      String key = "4dage1684dage168";
+
+//      //加密
+      String s = encryptAES(value, true);
+      System.out.println(s);
+      //解密
+      String k = decryptAES("9013E47C4A1181E70B697E956F7D8F16E776FB0F0D14FEF35C31158D889EAED9C0AACA53E67FE3F54468DE6F90B123E24E663E0AED062C1258A2CF937B17451958D115C4DDC7C317E1E06C174B748570F8618BBFD7A5AF56CFDDF48E2112BBD5033FBF152BB9966B8489EDD346201562", true);
+      System.out.println(k);
+
+   }
+
+}

+ 117 - 0
4dkankan-utils-reg/src/main/java/com/fdkankan/reg/DeflaterUtil.java

@@ -0,0 +1,117 @@
+package com.fdkankan.reg;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.util.Base64;
+import java.util.zip.DataFormatException;
+import java.util.zip.Deflater;
+import java.util.zip.Inflater;
+import java.util.zip.InflaterInputStream;
+
+/**
+    * DeflaterUtil 压缩字符串
+    */
+public class DeflaterUtil {
+      /**
+       * 压缩
+       */
+      public static String zipString(String unzipString) {
+
+         //使用指定的压缩级别创建一个新的压缩器。
+         Deflater deflater = new Deflater(Deflater.BEST_COMPRESSION);
+         //设置压缩输入数据。
+         deflater.setInput(unzipString.getBytes());
+         //当被调用时,表示压缩应该以输入缓冲区的当前内容结束。
+         deflater.finish();
+
+         final byte[] bytes = new byte[1024];
+         ByteArrayOutputStream outputStream = new ByteArrayOutputStream(1024);
+
+         while (!deflater.finished()) {
+            //压缩输入数据并用压缩数据填充指定的缓冲区。
+            int length = deflater.deflate(bytes);
+            outputStream.write(bytes, 0, length);
+         }
+         //关闭压缩器并丢弃任何未处理的输入。
+         deflater.end();
+         System.out.println(outputStream.toByteArray());
+         return Base64.getEncoder().encodeToString(outputStream.toByteArray());
+      }
+
+      /**
+       * 解压缩
+       */
+      public static String unzipString(String zipString) {
+         byte[] decode = Base64.getMimeDecoder().decode(zipString);
+         //创建一个新的解压缩器  https://www.yiibai.com/javazip/javazip_inflater.html
+
+         Inflater inflater = new Inflater();
+         //设置解压缩的输入数据。
+         inflater.setInput(decode);
+         final byte[] bytes = new byte[1024];
+         ByteArrayOutputStream outputStream = new ByteArrayOutputStream(1024);
+         try {
+            //finished() 如果已到达压缩数据流的末尾,则返回true。
+            while (!inflater.finished()) {
+               //将字节解压缩到指定的缓冲区中。
+               int length = inflater.inflate(bytes);
+               outputStream.write(bytes, 0, length);
+            }
+         } catch (DataFormatException e) {
+            e.printStackTrace();
+            return null;
+         } finally {
+            //关闭解压缩器并丢弃任何未处理的输入。
+            inflater.end();
+         }
+
+         return outputStream.toString();
+      }
+      public static byte[] compress(String data) throws IOException {
+         byte[] input = data.getBytes("UTF-8");
+         ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+         Deflater compressor = new Deflater();
+         compressor.setLevel(Deflater.BEST_COMPRESSION);
+         compressor.setInput(input);
+         compressor.finish();
+         byte[] buffer = new byte[1024];
+         while (!compressor.finished()) {
+            int count = compressor.deflate(buffer);
+            outputStream.write(buffer, 0, count);
+         }
+         outputStream.close();
+         return outputStream.toByteArray();
+      }
+
+      public static String decompress(byte[] data) throws IOException {
+         Inflater decompressor = new Inflater();
+         decompressor.setInput(data);
+         ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+         InflaterInputStream inflaterInputStream = new InflaterInputStream(
+                 new ByteArrayInputStream(data), decompressor);
+         byte[] buffer = new byte[1024];
+         int length;
+         while ((length = inflaterInputStream.read(buffer)) > 0) {
+            outputStream.write(buffer, 0, length);
+         }
+         outputStream.close();
+         byte[] output = outputStream.toByteArray();
+         return new String(output, "UTF-8");
+      }
+   public static void main(String[] args) throws IOException {
+      String data  = "9013E47C4A1181E70B697E956F7D8F16E776FB0F0D14FEF35C31158D889EAED9C0AACA53E67FE3F54468DE6F90B123E24E663E0AED062C1258A2CF937B17451958D115C4DDC7C317E1E06C174B748570F8618BBFD7A5AF56CFDDF48E2112BBD56B714370A75A094E3CADC98B349921755DCDAE2BC2660A29D4E33E34FA6AC5DC9B955DA1E43D35CDCBBB2956440FB83120CFD7E09EB4D8B62F5C981FD8D12798";
+      System.out.println(data.length());
+      String formattedString = DeflaterUtil.zipString(data);
+      System.out.println(formattedString.length());
+      System.out.println(formattedString);
+
+      // 还原为字符串
+      String restoredData = DeflaterUtil.unzipString(formattedString);
+      System.out.println(restoredData.length());
+      System.out.println(restoredData);
+      byte[] compress = compress(data);
+
+
+   }
+}

+ 21 - 0
4dkankan-utils-reg/src/main/java/com/fdkankan/reg/EnvType.java

@@ -0,0 +1,21 @@
+package com.fdkankan.reg;
+
+/**
+ * 标识系统部署环境是国内服还是国际服
+ */
+public enum EnvType {
+
+    PROD( "PROD"),
+    UAT( "UAT");
+
+    private String env;
+
+    private EnvType(String env) {
+        this.env = env;
+    }
+
+    public String env() {
+        return env;
+    }
+
+}

+ 200 - 0
4dkankan-utils-reg/src/main/java/com/fdkankan/reg/RegCodeUtil.java

@@ -0,0 +1,200 @@
+package com.fdkankan.reg;
+
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONObject;
+import com.fdkankan.reg.dto.CamRegDto;
+import com.fdkankan.reg.dto.CamRegSDto;
+import com.fdkankan.reg.dto.MachineRegDto;
+import lombok.Builder;
+import lombok.extern.slf4j.Slf4j;
+import java.util.ArrayList;
+import java.util.List;
+import cn.hutool.core.util.ObjUtil;
+
+/**
+ * @author Xiewj
+ * @date 2023/7/6
+ */
+@Slf4j
+@Builder
+public class RegCodeUtil {
+
+    private String env;
+
+
+    /***
+     * @description:生成安装码
+     * @author: Xiewj
+     * @date: 2023/7/6 15:01
+     * @param:  machineCode 机器码
+     * @return:
+     **/
+    public  String GenRegeditCode(String machineCode){
+        String s = Crypt.encryptAES(machineCode.trim()+"##"+this.env, true);
+        log.info("安装注册码:{}",s);
+        return s;
+    }
+
+    /***
+     * @description:生成相机激活码
+     * @author: Xiewj
+     * @date: 2023/7/6 15:01
+     * @param:  plaintext 需要加密的字符串 [{"SN": "SN000001", "TOSN": "", "OPTION": "ADD"}]
+     * @return:
+     **/
+    public  String GenRegeditCamCode(String plaintext){
+        String s = Crypt.encryptAES(plaintext.trim(), true);
+        log.info("相机注册码:{}",s);
+        log.info("相机注册码原始长度:{}",s.length());
+        String code = DeflaterUtil.zipString(s);
+        log.info("相机注册码压缩:{}",code);
+        log.info("相机注册码压缩长度:{}",code.length());
+
+        return code;
+    }
+    /***
+     * @description 获取激活数据
+     * @author: Xiewj
+     * @date: 2023/7/6 15:01
+     * @param:  plaintext 需要转换成对象的字符串
+     * @return:
+     **/
+    public  MachineRegDto ParseMachineCode(String plaintext){
+        try {
+            String source = Crypt.decryptAES(plaintext.trim(), true);
+            log.info("相机注册码解密:{}",source);
+            MachineRegDto t = JSON.toJavaObject(JSONObject.parseObject(source) , MachineRegDto.class);
+            return t;
+        }catch (Exception e){
+            e.printStackTrace();
+            throw new RuntimeException("校验失败");
+        }
+    }
+//    /***
+//     * @description 获取激活数据
+//     * @author: Xiewj
+//     * @date: 2023/7/6 15:01
+//     * @param:  plaintext 需要转换成对象的字符串
+//     * @return:
+//     **/
+//    public  CamRegDto ParseRegeditCamCode(String machineCode , String plaintext){
+//        try {
+//            //解压
+//            String code = DeflaterUtil.unzipString(plaintext);
+//            log.info("相机注册码解压:{}",code);
+//            String source = Crypt.decryptAES(code, true);
+//            log.info("相机注册码解密:{}",source);
+//            CamRegDto t = JSON.toJavaObject(JSONObject.parseObject(source) , CamRegDto.class);
+//            if (ObjUtil.isNull(t.getMachineCode()) && !t.getMachineCode().equals(machineCode)){
+//                throw new RuntimeException("校验失败");
+//            }
+//            return t;
+//        }catch (Exception e){
+//            e.printStackTrace();
+//            return null;
+//        }
+//    }
+
+    /***
+     * @description:生成相机激活码多个
+     * @author: Xiewj
+     * @date: 2023/7/6 15:01
+     * @param:  plaintext 需要加密的字符串 [{"SN": "SN000001", "TOSN": ""},{"SN": "SN000001", "TOSN": ""}]
+     * @return:
+     **/
+    public  String batchGenRegeditCamCode( CamRegSDto dtos){
+        dtos.setEnv(env);
+        String camCode = GenRegeditCamCode(JSONObject.toJSONString(dtos).toString());
+        return camCode;
+    }
+    /***
+     * @description 获取激活数据
+     * @author: Xiewj
+     * @date: 2023/7/6 15:01
+     * @param:  plaintext 需要转换成对象的字符串
+     * @return:
+     **/
+    public  CamRegSDto BatchParseRegeditCamCode(String machineCode,String plaintext){
+        try {
+            String trim=plaintext.trim();
+            if (trim.contains(" ")||trim.length()<=3){
+                throw new RuntimeException("校验失败");
+            }
+            //解压
+            String code = DeflaterUtil.unzipString(trim);
+            log.info("批量生成相机码解压:{}",code);
+            String source = Crypt.decryptAES(code, true);
+            CamRegSDto t = JSON.toJavaObject(JSONObject.parseObject(source) , CamRegSDto.class);
+            if (!env.equals(t.getEnv())){
+                throw new RuntimeException("环境比对失败");
+            }
+            if (ObjUtil.isNotNull(t.getMachineCode()) && !t.getMachineCode().equals(machineCode.trim()) ){
+                throw new RuntimeException("校验失败");
+            }
+            return t;
+        }catch (Exception e){
+            e.printStackTrace();
+            throw new RuntimeException("校验失败");
+        }
+    }
+    public static  void main(String[] args) {
+        RegCodeUtil uat = RegCodeUtil.builder().env("UAT").build();
+
+        String machineCode="8CA4224EB41BE3AD8998415EA0460F39845AC74625B3158A84AD18CEAC5FD6F4500CCC34309F7045F726AA6968F908C9";
+
+
+        //读取机器码
+        MachineRegDto machineRegDto = uat.ParseMachineCode(machineCode);
+        System.out.println(machineRegDto);
+
+
+        //生成安装注册码
+        String s = uat.GenRegeditCode(machineCode);
+
+//        CamRegDto camRegDto1=new CamRegDto();
+//        camRegDto1.setSn("00000001");
+//        camRegDto1.setMachineCode(machineCode);
+//        //生成相机注册码
+//        String camCode = GenRegeditCamCode( JSON.toJSONString(camRegDto1));
+//        //校验相机注册码
+//        CamRegDto camRegDto3 = ParseRegeditCamCode(machineCode,camCode);
+
+
+        List<CamRegDto> list=new ArrayList<>();
+
+//        CamRegDto camRegDto=new CamRegDto();
+////        camRegDto.setSn("dvt000007");
+////        camRegDto.setToSn("90d95cdb5");
+////        camRegDto.setToSn("dvt000007");
+//        camRegDto.setSn("a0ia7r137");
+//        camRegDto.setCameraType(9);
+
+//        CamRegDto camRegDto=new CamRegDto();
+//        camRegDto.setSn("a123456789");
+//        camRegDto.setCameraType(10);
+//        list.add(camRegDto);
+
+
+        CamRegDto camRegDto1=new CamRegDto();
+        camRegDto1.setSn("902ce60f5");
+//        camRegDto1.setToSn("c123456789");
+        camRegDto1.setCameraType(9);
+
+        list.add(camRegDto1);
+
+
+        CamRegSDto CamReg=new CamRegSDto();
+        CamReg.setMachineCode(machineCode);
+        CamReg.setCamRegs(list);
+        String camCode1 = uat.batchGenRegeditCamCode( CamReg);
+
+//        List<CamRegDto> list1 = BatchParseRegeditCamCode(machineCode+"a",camCode1);
+        CamRegSDto list1 = uat.BatchParseRegeditCamCode(machineCode,camCode1);
+
+
+
+
+        log.info("结束");
+    }
+
+}

+ 17 - 0
4dkankan-utils-reg/src/main/java/com/fdkankan/reg/dto/CamRegDto.java

@@ -0,0 +1,17 @@
+package com.fdkankan.reg.dto;
+
+import lombok.Data;
+
+/**
+ * Created by Xiewj on 2021/8/17 0017 8:49
+ */
+@Data
+public class CamRegDto {
+     /**
+     * {"SN": "SN000001", "TOSN": "", "OPTION": "ADD"}
+     **/
+    private String sn;
+    private String toSn;
+    private Integer cameraType; // 1,看看,9看见,10深时,11深光
+
+}

+ 18 - 0
4dkankan-utils-reg/src/main/java/com/fdkankan/reg/dto/CamRegSDto.java

@@ -0,0 +1,18 @@
+package com.fdkankan.reg.dto;
+
+import com.fdkankan.reg.EnvType;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * Created by Xiewj on 2021/8/17 0017 8:49
+ */
+@Data
+public class CamRegSDto {
+    private String machineCode;
+    private Long timestamp=System.currentTimeMillis();
+    private String env;
+    List<CamRegDto> camRegs;
+
+}

+ 12 - 0
4dkankan-utils-reg/src/main/java/com/fdkankan/reg/dto/MachineRegDto.java

@@ -0,0 +1,12 @@
+package com.fdkankan.reg.dto;
+
+import lombok.Data;
+
+/**
+ * Created by Xiewj on 2021/8/17 0017 8:49
+ */
+@Data
+public class MachineRegDto {
+    private String uuid;
+
+}

+ 7 - 0
4dkankan-utils-rubber-sheeting/pom.xml

@@ -38,6 +38,13 @@
             <artifactId>commons-codec</artifactId>
             <artifactId>commons-codec</artifactId>
             <version>${commons-codec.verion}</version>
             <version>${commons-codec.verion}</version>
         </dependency>
         </dependency>
+
+        <dependency>
+            <groupId>com.tencentcloudapi</groupId>
+            <artifactId>tencentcloud-sdk-java</artifactId>
+            <version>3.1.322</version>
+        </dependency>
+
     </dependencies>
     </dependencies>
 
 
 </project>
 </project>

+ 81 - 0
4dkankan-utils-rubber-sheeting/src/main/java/com/fdkankan/rubbersheeting/TencentScalingService.java

@@ -0,0 +1,81 @@
+package com.fdkankan.rubbersheeting;
+
+import com.tencentcloudapi.as.v20180419.AsClient;
+import com.tencentcloudapi.as.v20180419.models.ScaleOutInstancesRequest;
+import com.tencentcloudapi.as.v20180419.models.ScaleOutInstancesResponse;
+import com.tencentcloudapi.as.v20180419.models.StopAutoScalingInstancesRequest;
+import com.tencentcloudapi.as.v20180419.models.StopAutoScalingInstancesResponse;
+import com.tencentcloudapi.common.Credential;
+import com.tencentcloudapi.common.exception.TencentCloudSDKException;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.stereotype.Component;
+
+import java.util.Map;
+
+/**
+ * Created by Hb_zzZ on 2020/8/25.
+ */
+@Slf4j
+@Component
+@ConditionalOnProperty(name = "scaling.type",havingValue = "tencent")
+public class TencentScalingService implements ScalingService{
+
+    @Value("${accessKey.id:xxx}")
+    private static String accessKeyId;
+    @Value("${accessKey.secret:xxx}")
+    private static String accessKeySecret;
+    @Value("${scaling.region:ap-guangzhou}")
+    private String region;
+    @Value("${scaling.group.id:asg-hv68oe36}")
+    private String groupId;
+
+    private AsClient getAsClient(){
+        Credential cred = new Credential(accessKeyId, accessKeySecret);
+        AsClient client = new AsClient(cred, region);
+        return client;
+    }
+
+
+    @Override
+    public String createEcs(){
+        AsClient asClient = this.getAsClient();
+        ScaleOutInstancesRequest req = new ScaleOutInstancesRequest();
+        req.setAutoScalingGroupId(groupId);
+        req.setScaleOutNumber(1L);
+        ScaleOutInstancesResponse resp = null;
+        try {
+            resp = asClient.ScaleOutInstances(req);
+        } catch (TencentCloudSDKException e) {
+            log.error("启动弹性伸缩示例失败", e);
+            return null;
+        }
+        return ScaleOutInstancesResponse.toJsonString(resp);
+    }
+
+    @Override
+    public String createEcsByConfig(Map<String, String> configs) {
+        return null;
+    }
+
+
+    @Override
+    public  String deleteEcs(String id){
+        AsClient asClient = this.getAsClient();
+        StopAutoScalingInstancesRequest req2 = new StopAutoScalingInstancesRequest();
+        req2.setAutoScalingGroupId(groupId);
+        req2.setInstanceIds(new String[]{id});
+        req2.setStoppedMode("STOP_CHARGING");
+        StopAutoScalingInstancesResponse response = null;
+        try {
+            response = asClient.StopAutoScalingInstances(req2);
+        } catch (TencentCloudSDKException e) {
+            log.error("停止弹性伸缩示例失败,实例id:{}",id);
+            return null;
+        }
+        return StopAutoScalingInstancesResponse.toJsonString(response);
+    }
+
+
+}

+ 5 - 0
4dkankan-utils-sms/pom.xml

@@ -48,6 +48,11 @@
             <version>1.11.1032</version>
             <version>1.11.1032</version>
         </dependency>
         </dependency>
         <dependency>
         <dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>dysmsapi20170525</artifactId>
+            <version>2.0.23</version>
+        </dependency>
+        <dependency>
             <groupId>com.sun.mail</groupId>
             <groupId>com.sun.mail</groupId>
             <artifactId>javax.mail</artifactId>
             <artifactId>javax.mail</artifactId>
             <version>1.5.4</version>
             <version>1.5.4</version>

+ 2 - 0
pom.xml

@@ -21,12 +21,14 @@
         <module>4dkankan-utils-fyun-parent</module>
         <module>4dkankan-utils-fyun-parent</module>
         <module>4dkankan-utils-fyun-oss</module>
         <module>4dkankan-utils-fyun-oss</module>
         <module>4dkankan-utils-fyun-s3</module>
         <module>4dkankan-utils-fyun-s3</module>
+        <module>4dkankan-utils-fyun-cos</module>
         <module>4dkankan-utils-fyun-local</module>
         <module>4dkankan-utils-fyun-local</module>
         <module>4dkankan-utils-model</module>
         <module>4dkankan-utils-model</module>
         <module>4dkankan-utils-wechat</module>
         <module>4dkankan-utils-wechat</module>
         <module>4dkankan-utils-image</module>
         <module>4dkankan-utils-image</module>
         <module>4dkankan-utils-sensitive-word</module>
         <module>4dkankan-utils-sensitive-word</module>
         <module>4dkankan-utils-elasticsearch</module>
         <module>4dkankan-utils-elasticsearch</module>
+        <module>4dkankan-utils-reg</module>
     </modules>
     </modules>
 
 
     <groupId>com.fdkankan</groupId>
     <groupId>com.fdkankan</groupId>