Переглянути джерело

Merge remote-tracking branch 'origin/featrue-local' into featrue-local

dengsixing 3 роки тому
батько
коміт
baf02a3479

+ 30 - 17
pom.xml

@@ -54,6 +54,16 @@
             <groupId>com.fdkankan</groupId>
             <artifactId>4dkankan-common-web</artifactId>
             <version>3.0.0-SNAPSHOT</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>com.alibaba.cloud</groupId>
+                    <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>com.alibaba.cloud</groupId>
+                    <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
+                </exclusion>
+            </exclusions>
         </dependency>
 
         <dependency>
@@ -96,29 +106,32 @@
             <artifactId>firebase-admin</artifactId>
             <version>6.8.1</version>
         </dependency>
+        <dependency>
+            <groupId>com.aliyun.oss</groupId>
+            <artifactId>aliyun-sdk-oss</artifactId>
+            <version>3.8.0</version>
+        </dependency>
+        <dependency>
+            <groupId>io.minio</groupId>
+            <artifactId>minio</artifactId>
+            <version>8.2.2</version>
+            <exclusions>
+                <exclusion>
+                    <artifactId>okio</artifactId>
+                    <groupId>com.squareup.okio</groupId>
+                </exclusion>
+                <exclusion>
+                    <artifactId>okhttp</artifactId>
+                    <groupId>com.squareup.okhttp3</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
 
     </dependencies>
 
     <dependencyManagement>
 
         <dependencies>
-
-            <dependency>
-                <groupId>com.alibaba.cloud</groupId>
-                <artifactId>spring-cloud-alibaba-dependencies</artifactId>
-                <version>2.2.7.RELEASE</version>
-                <type>pom</type>
-                <scope>import</scope>
-            </dependency>
-
-            <dependency>
-                <groupId>org.springframework.cloud</groupId>
-                <artifactId>spring-cloud-dependencies</artifactId>
-                <version>${spring.cloud-version}</version>
-                <type>pom</type>
-                <scope>import</scope>
-            </dependency>
-
             <dependency>
                 <groupId>cn.hutool</groupId>
                 <artifactId>hutool-all</artifactId>

+ 149 - 0
src/main/java/com/fdkankan/scene/config/FdkkLaserConfig.java

@@ -0,0 +1,149 @@
+package com.fdkankan.scene.config;
+
+import cn.hutool.core.io.FileUtil;
+import lombok.Data;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.stereotype.Component;
+
+import javax.annotation.PostConstruct;
+
+/**
+ * 读取项目相关配置
+ *
+ * @author fdkk
+ */
+@Component
+@ConfigurationProperties(prefix = "fdkk")
+@Data
+public class FdkkLaserConfig {
+
+
+    /**
+     * 上传路径
+     */
+    private static String profile;
+
+    /**
+     * 区分雪花生成
+     */
+    private String workId;
+
+
+    /**
+     * 是否本地化文件存储
+     */
+    private static boolean isLocalization;
+    /**
+     * 本地化化部署,是否启用软连接
+     */
+    private static boolean isLink;
+
+    /**
+     * 是否使用文件存储系统
+     */
+    private static boolean isBucket;
+
+    /**
+     * 生成模型的路径
+     */
+    public String buildModelPath;
+    /**
+     * 算法调用
+     */
+    public String buildCallPath;
+    /**
+     * java存放路径
+     */
+    public String binPath;
+
+    /**
+     * 后端文件保存路径
+     */
+    public String myBackBasePath;
+
+    /**
+     * OSS默认路径
+     */
+    public String defaultFolder;
+
+
+
+
+    @PostConstruct
+    private void init() {
+        FileUtil.mkdir(buildCallPath);
+        FileUtil.mkdir(buildModelPath);
+        FileUtil.mkdir(FdkkLaserConfig.profile);
+    }
+
+
+    public static String getProfile() {
+        return FdkkLaserConfig.profile;
+    }
+
+    public void setProfile(String profile) {
+        FdkkLaserConfig.profile = profile;
+    }
+
+    public String getWorkId() {
+        return workId;
+    }
+
+    public void setWorkId(String workId) {
+        this.workId = workId;
+    }
+
+
+    public static boolean isLocalization() {
+        return FdkkLaserConfig.isLocalization;
+    }
+
+    public void setIsLocalization(boolean isLocalization) {
+        FdkkLaserConfig.isLocalization = isLocalization;
+    }
+
+    public static boolean isIsLink() {
+        return FdkkLaserConfig.isLink;
+    }
+
+    public static void setIsLink(boolean isLink) {
+        FdkkLaserConfig.isLink = isLink;
+    }
+
+
+    public static boolean isIsBucket() {
+        return FdkkLaserConfig.isBucket;
+    }
+
+    public static void setIsBucket(boolean isBucket) {
+        FdkkLaserConfig.isBucket = isBucket;
+    }
+
+    /**
+     * 获取导入上传路径
+     */
+    public static String getImportPath() {
+        return FdkkLaserConfig.getProfile() + "/import";
+    }
+
+    /**
+     * 获取头像上传路径
+     */
+    public static String getAvatarPath() {
+        return FdkkLaserConfig.getProfile() + "/avatar";
+    }
+
+    /**
+     * 获取下载路径
+     */
+    public static String getDownloadPath() {
+        return FdkkLaserConfig.getProfile() + "/download/";
+    }
+
+    /**
+     * 获取上传路径
+     */
+    public static String getUploadPath() {
+        return FdkkLaserConfig.getProfile() + "/upload";
+    }
+}

+ 46 - 0
src/main/java/com/fdkankan/scene/config/ServiceConfig.java

@@ -0,0 +1,46 @@
+package com.fdkankan.scene.config;
+
+import org.springframework.boot.web.context.WebServerInitializedEvent;
+import org.springframework.context.ApplicationListener;
+import org.springframework.context.annotation.Configuration;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+@Configuration
+public class ServiceConfig implements ApplicationListener<WebServerInitializedEvent> {
+    @Override
+    public void onApplicationEvent(WebServerInitializedEvent event) {
+        // 项目启动获取启动的端口号
+        ServiceConfig.serverPort = event.getWebServer().getPort();
+    }
+
+    /**
+     * 当前服务使用的端口号
+     */
+    private static int serverPort;
+
+    public int getServerPort() {
+        return ServiceConfig.serverPort;
+    }
+
+    public void setServerPort(int serverPort) {
+        ServiceConfig.serverPort = serverPort;
+    }
+
+    /**
+     * 获取请求基地址
+     *
+     * @return String 请求基地址
+     * @date 2021/11/15
+     **/
+    public String getBaseUrl() {
+        InetAddress address = null;
+        try {
+            address = InetAddress.getLocalHost();
+        } catch (UnknownHostException e) {
+            e.printStackTrace();
+        }
+        return "http://" + address.getHostAddress() + ":" + getServerPort();
+    }
+}

+ 150 - 0
src/main/java/com/fdkankan/scene/constant/CmdConstant.java

@@ -0,0 +1,150 @@
+package com.fdkankan.scene.constant;
+
+
+/**
+ * Created by owen on 2020/12/31 0031 14:22
+ */
+public class CmdConstant {
+
+
+    /**
+     * ossUtil上传目录
+     * ./ossutil cp -r localfolder/ oss://examplebucket/desfolder/
+     * opt/ossutil/ossutil64 cp -r /root/owen/720yun/vtour/ oss://oss-xiaoan/720yun_fd_manage/
+     *
+     */
+//    public final static String OSSUTIL_UPLOAD_DIR = "/opt/ossutil/ossutil64 cp -r /mnt/720yun_fd_manage_data/@sceneCode oss://oss-xiaoan/720yun_fd_manage/@sceneCode";
+
+    /**
+     * 用脚本的好处会自动结束线程, java直接跑命令容易出问题
+     * 调用oss上传目录脚本
+     * bash /opt/ossutil/ossupload.sh @dir @ossDir
+     * bash /opt/ossutil/ossupload.sh /mnt/720yun_fd_manage_data/fd720_1A4Tba8mA 720yun_fd_manage/fd720_1A4Tba8mA
+     *
+     * @uploadDir :服务器资源目录
+     * @target oss目录名字
+     * @mergeCode 合并的场景码
+     */
+//    public final static String OSSUTIL_UPLOAD_DIR = "bash /opt/ossutil/ossupload.sh /mnt/720yun_fd_manage_data/@sceneCode 720yun_fd_manage/@sceneCode";
+//    public final static String OSSUTIL_UPLOAD_DIR_CHUNK = "bash /root/user/java/jar_run/ossupload.sh @uploadDir data/@sceneCode/data/chunk1/@target";
+    // 2021-08-26 - chunk1 -> 改场景码
+    public final static String OSSUTIL_UPLOAD_DIR_CHUNK = "bash /opt/ossutil/ossupload.sh @uploadDir @defaultFolder/@sceneCode/data/@mergeCode/@target";
+
+    public final static String OSSUTIL_UPLOAD_DIR = "bash /opt/ossutil/ossupload.sh @uploadDir @target";
+
+    public final static String OSSUTIL_RM_DIR = "bash /root/user/java/jar_run/ossrm.sh @target";
+
+
+    public final static String MINIO_OSSUTIL_UPLOAD_DIR_CHUNK = "bash /opt/ossutil/minioupload.sh @uploadDir @defaultFolder/@sceneCode/data/@mergeCode/";
+    // MINIO 上传文件夹命令
+    public final static String MINIO_UTIL_UPLOAD_DIR = "bash /opt/ossutil/minioupload.sh @uploadDir/ @target";
+
+    public final static String MINIO_UTIL_RM_DIR = "bash /opt/ossutil/miniorm.sh  @target";
+
+    /**
+     * 2021-08-17
+     * 剪切模型命令, 这个需要在nas共享目录, 测试服务器,跟算法服务器是分开的
+     * bash /home/ubuntu/bin/PotreeConverter.sh /mnt/data/00001002/872819408496492544/74ee2a39e656_202108051135248650/results/laserData/laser.las
+     * /mnt/data/00001002/872819408496492544/74ee2a39e656_202108051135248650/results/laserData/indoor_cut.las
+     * /mnt/data/00001002/872819408496492544/74ee2a39e656_202108051135248650/results/laserData/cut_param.json
+     * bash /home/ubuntu/bin/PotreeConverter.sh inPath outPath inCutParam;
+     */
+    public final static String CUT_MODEL = "bash /home/ubuntu/bin/PotreeConverter.sh @inPath @outPath @cutParam";
+
+
+    /**
+     * ossUtil下载目录
+     *
+     * @downloadDir oss需要下载的目录
+     * @target 服务器存放位置(会把当前目录也下载)
+     */
+    public final static String OSSUTIL_DOWNLOAD_DIR = "bash /root/user/java/jar_run/ossdownload.sh @downloadDir @target";
+
+    public final static String RM_Folder = "rm -rf @Folder";
+    public final static String RM_Folder_WIN = "rmdir @Folder /s";
+
+    public final static String MV_Folder = "mv -f @Folder @Target";
+
+    public final static String MV_Folder_WIN = "move /y @Folder @Target";
+
+
+    public final static String CP_Folder = "cp -r -f @Folder @Target";
+    public final static String CP_Folder_WIN = "xcopy /y /s /f /h  @Folder @Target";
+
+    public final static String MK_LINK_DIR = "sudo ln -s /J  @Target @Link";
+
+    public final static String MK_LINK_DIR_WIN = "mklink /J @Link @Target";
+
+    public final static String MK_LINK_FILE = "sudo ln  @Target @Link";
+    public final static String MK_LINK_FILE_WIN = "mklink /H @Link @Target";
+
+    public final static String OBJ_TO_GLB = "obj2gltf @inPath @outPath";
+    public final static String OBJ_TO_GLB_WIN = "objtoglb.exe @inPath @outPath";
+    /**
+     * zip merge_cut.zip merge_cut.las
+     **/
+    public final static String ZIP = "cd @path && zip -r @target @inPath";
+
+    /**
+     * 2021-09-23
+     * 英达:多数据集模型剪切
+     * bash /home/ubuntu/bin/PotreeConverter.sh "" xxx/xxx.las xxx/merge_cut_param.json"
+     * 三个参数,合并裁剪的,第一个参数为空字符串"", 第二个是输出.las路径,第三个是merge_cut_param.json文件路径
+     * outPath: 是输出.las路径
+     * inPath: merge_cut_param.json文件路径
+     */
+    public final static String MERGE_CUT_MODEL = "bash /home/ubuntu/bin/PotreeConverter.sh cut @outPath @inPath";
+    public final static String MERGE_CUT_MODEL_WIN = "PotreeConverter.bat cut @outPath @inPath";
+
+
+    /**
+     * 2022年3月26日15:58:37
+     * 英达:点云文件坐标转换
+     *
+     * @param json文件路径  @inPath 输入las模型路径 @outPath 输出las模型路径
+     */
+    public final static String CONVERTER_ADD_GEO = "bash /home/ubuntu/bin/PotreeConverter.sh @param @inPath @outPath ";
+
+    public final static String CONVERTER_ADD_GEO_WIN = "PotreeConverter.bat @param @inPath @outPath ";
+
+    //生成模型的命令
+    public static final String BUILD_MODEL_COMMAND = "bash /home/ubuntu/bin/Launcher.sh  @inPath";
+    public static final String BUILD_MODEL_COMMAND_WIN = "Launcher.bat @inPath";
+
+    //生成模型的命令
+    public static final String KILL_BUILD_MODEL_COMMAND = "ps -ef | grep MainLoader.exe | grep -v grep | awk '{print $2}' | xargs kill -9";
+
+    public static final String KILL_BUILD_MODEL_COMMAND_WIN = "taskkill /f /im MainLoader.exe";
+
+    public static final String AUTH_LICENSE_WIN = "Launcher.bat @inPath";
+
+    /**
+     * 2021-09-24
+     * 世超: 平面图切图
+     * 需要参数:
+     * 工作目录
+     * data.json -> {"split_type":"SPLIT_V15","skybox_type":"SKYBOX_V5"}
+     * extras
+     * info.json
+     * xxx.png
+     * bash /home/ubuntu/bin/Launcher.sh ${工作路径}
+     */
+    public final static String TILED_MAP = "bash /home/ubuntu/bin/Laser-Launcher.sh @inPath";
+    public final static String TILED_MAP_WIN = "Launcher.bat @inPath";
+
+    /**
+     * las to bin
+     * bash PotreeConverter_webcloud_bin.sh /mnt/data/00001050/933817767755251712/00001050_202201202011578010_laserData/cloud_extras/point.las
+     * /mnt/data/00001050/933817767755251712/00001050_202201202011578010_laserData/cloud_extras
+     */
+    public final static String LAS_TO_BIN = "bash  /home/ubuntu/bin/PotreeConverter.sh @inPath @outPath ''";
+    public final static String LAS_TO_BIN_WIN = "PotreeConverter.bat @inPath @outPath ''";
+
+    /***
+     * # 模型检查  check 路径 输出json  {"check_result":"0","model_path":"add_geo.las"}  0/1 模型正确是1,模型不正确是0
+     */
+    public final static String CHECK_LASER = "bash  /home/ubuntu/bin/PotreeConverter.sh check @inPath @outPath";
+
+    public final static String CHECK_LASER_WIN = "PotreeConverter.bat check @inPath @outPath";
+
+}

+ 11 - 0
src/main/java/com/fdkankan/scene/oss/Consumer.java

@@ -0,0 +1,11 @@
+package com.fdkankan.scene.oss;
+
+/**
+ * @author Xiewj
+ * @date 2021/9/29
+ */
+
+public interface Consumer<T> {
+
+   void accept(T t);
+}

+ 57 - 0
src/main/java/com/fdkankan/scene/oss/InnerUtils.java

@@ -0,0 +1,57 @@
+package com.fdkankan.scene.oss;
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+import java.nio.charset.StandardCharsets;
+/**
+ * @author Xiewj
+ * @date 2021/9/29
+ */
+public class InnerUtils {
+    public static String getUrlPath(String url) {
+        try {
+            String path = new URL(url).getPath();
+            return URLDecoder.decode(path, StandardCharsets.UTF_8.name());
+        } catch (MalformedURLException | UnsupportedEncodingException e) { // Ignore
+        }
+        return "";
+    }
+
+    public static String generateHost(String endpoint, String bucket) {
+        String http = "http://";
+        String https = "https://";
+        if (endpoint.startsWith(http)) {
+            return http + bucket + "." + endpoint.substring(http.length());
+        }
+        if (endpoint.startsWith(https)) {
+            return https + bucket + "." + endpoint.substring(https.length());
+        }
+        return http + bucket + "." + endpoint;
+    }
+
+
+    public static String decodeUrl(String url) {
+        try {
+            return URLDecoder.decode(url, StandardCharsets.UTF_8.name());
+        } catch (UnsupportedEncodingException e) {
+            throw new RuntimeException("Never Happen!", e);
+        }
+    }
+
+    public static String encodeUrl(String url) {
+        try {
+            return URLEncoder.encode(url, StandardCharsets.UTF_8.name());
+        } catch (UnsupportedEncodingException e) {
+            throw new RuntimeException("Never Happen!", e);
+        }
+    }
+
+    public static void checkArgument(boolean expect, String messageFormat, Object... args) {
+        if (!expect) {
+            String message = String.format(messageFormat, args);
+            throw new IllegalArgumentException(message);
+        }
+    }
+}

+ 93 - 0
src/main/java/com/fdkankan/scene/oss/OssOptions.java

@@ -0,0 +1,93 @@
+package com.fdkankan.scene.oss;
+
+
+import java.io.File;
+import java.io.InputStream;
+import java.util.List;
+
+/**
+ * 提供简化上传/下载的基本操作,复杂操作请使用原始客户端OSS.
+ * <p>
+ * 上传文件: uploadXxx 下载文件: downloadXxx
+ */
+public interface OssOptions<T> {
+
+    //------------------------------------------------------------------
+    // 上传文件
+    //------------------------------------------------------------------
+    String uploadFile(String pathKey, String filePath);
+
+    void rmFileCmd(String targetDir);
+
+    void uploadFileDirCmd(String uploadDir, String target);
+
+    void uploadFileChunkCmd(String defaultFolder, String sceneCode, String uploadDir, String targetDir, String mergeCode);
+
+
+    String uploadFile(String bucket, String pathKey, String filePath);
+
+    String uploadFileText(String pathKey, String text);
+
+    String uploadFileText(String bucket, String pathKey, String text);
+
+    String uploadFileBase64Image(String pathKey, String base64);
+
+    String uploadFileBase64Image(String bucket, String pathKey, String base64);
+
+    String uploadFileBytes(String pathKey, byte[] bytes);
+
+    String uploadFileBytes(String bucket, String pathKey, byte[] bytes);
+
+    String uploadFileStream(String pathKey, InputStream stream);
+
+    String uploadFileStream(String bucket, String pathKey, InputStream stream);
+
+    String uploadFileImage(String pathKey, String filePath);
+
+    String uploadFileImage(String bucket, String pathKey, String filePath);
+
+    //------------------------------------------------------------------
+    // 下载文件
+    //------------------------------------------------------------------
+
+    File downloadFileTmp(String pathKey);
+
+    File downloadFileTmp(String bucket, String pathKey);
+
+    T downloadFile(String pathKey, String file);
+
+    T downloadFile(String bucket, String pathKey, String file);
+
+    T downloadFile(String pathKey, Consumer<InputStream> handler);
+
+    T downloadFile(String bucket, String pathKey, Consumer<InputStream> handler);
+
+    //------------------------------------------------------------------
+    // 辅助方法
+    //------------------------------------------------------------------
+
+
+    Boolean copyObject(String oldPath, String newPath);
+
+    Boolean copyObject(String bucket, String oldPath, String toBucket, String newPath);
+
+
+    void deleteObject(String keyName);
+
+    void deleteObject(String bucket, String keyName);
+
+    /**
+     * 获取文件夹
+     *
+     * @param keyName
+     * @return
+     */
+    List<String> getFileFolder(String keyName);
+
+    List<String> getFileFolder(String bucket, String keyName);
+
+    boolean doesObjectExist(String bucket, String keyName);
+
+    boolean doesObjectExist(String keyName);
+
+}

+ 421 - 0
src/main/java/com/fdkankan/scene/oss/OssUtil.java

@@ -0,0 +1,421 @@
+package com.fdkankan.scene.oss;
+
+import cn.hutool.core.io.FileUtil;
+import com.fdkankan.scene.config.FdkkLaserConfig;
+import com.fdkankan.scene.config.ServiceConfig;
+import com.fdkankan.scene.oss.aliyun.AliyunOssTemplate;
+import com.fdkankan.scene.oss.minio.MinioOssTemplate;
+import com.fdkankan.scene.util.CmdBuildUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.util.Base64Utils;
+
+import java.io.File;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.List;
+import java.util.regex.Matcher;
+
+
+@Component
+public class OssUtil {
+
+    @Autowired
+    AliyunOssTemplate aliyunOssTemplate;
+    @Autowired
+    MinioOssTemplate minioOssTemplate;
+    @Autowired
+    FdkkLaserConfig fdkkLaserConfig;
+    @Autowired
+    ServiceConfig serviceConfig;
+
+    public String getPathKey(String sceneCode, String type, String fileName) {
+        return fdkkLaserConfig.getDefaultFolder() + "/" + sceneCode + "/temp/" + type + "/" + fileName;
+    }
+
+    public void rmFileCmd(String targetDir) {
+        if (FdkkLaserConfig.isIsBucket()) {
+            if (FdkkLaserConfig.isLocalization()) {
+                minioOssTemplate.rmFileCmd(targetDir);
+            } else {
+                aliyunOssTemplate.rmFileCmd(targetDir);
+            }
+        } else {
+            FileUtil.del(FdkkLaserConfig.getProfile() + File.separator + targetDir.replaceAll("/", Matcher.quoteReplacement(File.separator)));
+        }
+
+    }
+
+    public String getHostByBucket(String bucket) {
+        if (FdkkLaserConfig.isIsBucket()) {
+            if (FdkkLaserConfig.isLocalization()) {
+                return minioOssTemplate.calculateUrl(bucket, "");
+            } else {
+                return aliyunOssTemplate.calculateUrl(bucket, "");
+            }
+        } else {
+            return serviceConfig.getBaseUrl() + "profile";
+        }
+    }
+
+
+    public void uploadFileChunkCmd(String defaultFolder, String sceneCode, String uploadDir, String targetDir, String mergeCode, boolean isLink) {
+        if (FdkkLaserConfig.isIsBucket()) {
+            if (FdkkLaserConfig.isLocalization()) {
+                minioOssTemplate.uploadFileChunkCmd(defaultFolder, sceneCode, uploadDir, targetDir, mergeCode);
+            } else {
+                aliyunOssTemplate.uploadFileChunkCmd(defaultFolder, sceneCode, uploadDir, targetDir, mergeCode);
+            }
+        } else {
+            if (isLink) {
+                String path = FdkkLaserConfig.getProfile() + File.separator + defaultFolder + File.separator + sceneCode + File.separator + "data" + File.separator + mergeCode;
+                String targetPath = path + File.separator + targetDir;
+                if (!FileUtil.exist(path)) {
+                    FileUtil.mkdir(path);
+                }
+                if (FileUtil.exist(targetPath)) {
+                    FileUtil.del(targetPath);
+                }
+                CmdBuildUtil.MkLinkDir(targetPath, FileUtil.file(uploadDir).getAbsolutePath());
+            } else {
+                String path = FdkkLaserConfig.getProfile() + File.separator + defaultFolder + File.separator + sceneCode + File.separator + "data" + File.separator + mergeCode;
+                if (FileUtil.exist(FileUtil.file(uploadDir))) {
+                    FileUtil.copy(
+                            FileUtil.file(uploadDir),
+                            FileUtil.file(path),
+                            true);
+                }
+            }
+
+        }
+    }
+
+
+    public void uploadFileDirCmd(String uploadDir, String target, Boolean isLink) {
+        if (FdkkLaserConfig.isIsBucket()) {
+            if (FdkkLaserConfig.isLocalization()) {
+                minioOssTemplate.uploadFileDirCmd(uploadDir, target);
+            } else {
+                aliyunOssTemplate.uploadFileDirCmd(uploadDir, target);
+            }
+        } else {
+            if (isLink) {
+                String path = FdkkLaserConfig.getProfile() + File.separator + target;
+                File folder = FileUtil.file(path);
+                if (!FileUtil.exist(folder.getParent())) {
+                    FileUtil.mkdir(folder.getParent());
+                }
+                CmdBuildUtil.MkLinkDir(folder.getAbsolutePath(), FileUtil.file(uploadDir).getAbsolutePath());
+            } else {
+                File[] ls = FileUtil.ls(uploadDir);
+                for (File l : ls) {
+                    FileUtil.copy(
+                            FileUtil.file(l),
+                            FileUtil.file(FdkkLaserConfig.getProfile() + File.separator + target),
+                            true);
+                }
+            }
+
+        }
+
+    }
+
+
+    public String uploadFile(String pathKey, String filePath, boolean isLink) {
+        if (FdkkLaserConfig.isIsBucket()) {
+            if (FdkkLaserConfig.isLocalization()) {
+                return minioOssTemplate.uploadFile(pathKey, filePath);
+            } else {
+                return aliyunOssTemplate.uploadFile(pathKey, filePath);
+            }
+        } else {
+            if (isLink) {
+                File file = FileUtil.file(filePath);
+                if (!FileUtil.exist(file.getParent())) {
+                    FileUtil.mkdir(file.getParent());
+                }
+                File pathKeyFile = FileUtil.file(FdkkLaserConfig.getProfile() + File.separator + pathKey);
+                if (!FileUtil.exist(pathKeyFile.getParent())) {
+                    FileUtil.mkdir(pathKeyFile.getParent());
+                }
+                CmdBuildUtil.MkLinkFile(pathKeyFile.getAbsolutePath(), file.getAbsolutePath());
+            } else {
+                FileUtil.copy(filePath,
+                        FdkkLaserConfig.getProfile() + File.separator + pathKey,
+                        true);
+            }
+            return pathKey;
+        }
+    }
+
+
+    public String uploadFileText(String pathKey, String text) {
+        if (FdkkLaserConfig.isIsBucket()) {
+            if (FdkkLaserConfig.isLocalization()) {
+                return minioOssTemplate.uploadFileText(pathKey, text);
+            } else {
+                return aliyunOssTemplate.uploadFileText(pathKey, text);
+            }
+        } else {
+            FileUtil.writeBytes(text.getBytes(StandardCharsets.UTF_8), FdkkLaserConfig.getProfile() + File.separator + pathKey);
+            return pathKey;
+        }
+    }
+
+
+    public String uploadFileText(String bucket, String pathKey, String text) {
+        if (FdkkLaserConfig.isIsBucket()) {
+            if (FdkkLaserConfig.isLocalization()) {
+                return minioOssTemplate.uploadFileText(bucket, pathKey, text);
+            } else {
+                return aliyunOssTemplate.uploadFileText(bucket, pathKey, text);
+            }
+        } else {
+            FileUtil.writeBytes(text.getBytes(StandardCharsets.UTF_8), FdkkLaserConfig.getProfile() + File.separator + pathKey);
+            return pathKey;
+        }
+    }
+
+
+    public String uploadFileBase64Image(String pathKey, String base64) {
+        if (FdkkLaserConfig.isIsBucket()) {
+            if (FdkkLaserConfig.isLocalization()) {
+                return minioOssTemplate.uploadFileBase64Image(pathKey, base64);
+            } else {
+                return aliyunOssTemplate.uploadFileBase64Image(pathKey, base64);
+            }
+        } else {
+            byte[] bytes = Base64Utils.decodeFromString(base64);
+            FileUtil.writeBytes(bytes, FdkkLaserConfig.getProfile() + File.separator + pathKey);
+            return pathKey;
+        }
+    }
+
+
+    public String uploadFileBase64Image(String bucket, String pathKey, String base64) {
+        if (FdkkLaserConfig.isIsBucket()) {
+            if (FdkkLaserConfig.isLocalization()) {
+                return minioOssTemplate.uploadFileBase64Image(bucket, pathKey, base64);
+            } else {
+                return aliyunOssTemplate.uploadFileBase64Image(bucket, pathKey, base64);
+            }
+        } else {
+            byte[] bytes = Base64Utils.decodeFromString(base64);
+            FileUtil.writeBytes(bytes, FdkkLaserConfig.getProfile() + File.separator + pathKey);
+            return pathKey;
+        }
+    }
+
+
+    public String uploadFileBytes(String pathKey, byte[] bytes) {
+        if (FdkkLaserConfig.isIsBucket()) {
+            if (FdkkLaserConfig.isLocalization()) {
+                return minioOssTemplate.uploadFileBytes(pathKey, bytes);
+            } else {
+                return aliyunOssTemplate.uploadFileBytes(pathKey, bytes);
+            }
+        } else {
+            FileUtil.writeBytes(bytes, FdkkLaserConfig.getProfile() + File.separator + pathKey);
+            return pathKey;
+        }
+    }
+
+
+    public String uploadFileBytes(String bucket, String pathKey, byte[] bytes) {
+        if (FdkkLaserConfig.isIsBucket()) {
+            if (FdkkLaserConfig.isLocalization()) {
+                return minioOssTemplate.uploadFileBytes(bucket, pathKey, bytes);
+            } else {
+                return aliyunOssTemplate.uploadFileBytes(bucket, pathKey, bytes);
+            }
+        } else {
+            FileUtil.writeBytes(bytes, FdkkLaserConfig.getProfile() + File.separator + pathKey);
+            return pathKey;
+        }
+    }
+
+
+    public String uploadFileStream(String pathKey, InputStream stream) {
+        if (FdkkLaserConfig.isIsBucket()) {
+            if (FdkkLaserConfig.isLocalization()) {
+                return minioOssTemplate.uploadFileStream(pathKey, stream);
+            } else {
+                return aliyunOssTemplate.uploadFileStream(pathKey, stream);
+            }
+        } else {
+            FileUtil.writeFromStream(stream, FdkkLaserConfig.getProfile() + File.separator + pathKey);
+            return pathKey;
+        }
+    }
+
+
+    public String uploadFileStream(String bucket, String pathKey, InputStream stream) {
+        if (FdkkLaserConfig.isIsBucket()) {
+            if (FdkkLaserConfig.isLocalization()) {
+                return minioOssTemplate.uploadFileStream(bucket, pathKey, stream);
+            } else {
+                return aliyunOssTemplate.uploadFileStream(bucket, pathKey, stream);
+            }
+        } else {
+            FileUtil.writeFromStream(stream, FdkkLaserConfig.getProfile() + File.separator + pathKey);
+            return pathKey;
+        }
+    }
+
+
+    public String uploadFileImage(String pathKey, String filePath, boolean isLink) {
+        if (FdkkLaserConfig.isIsBucket()) {
+            if (FdkkLaserConfig.isLocalization()) {
+                return minioOssTemplate.uploadFileImage(pathKey, filePath);
+            } else {
+                return aliyunOssTemplate.uploadFileImage(pathKey, filePath);
+            }
+        } else {
+            if (isLink) {
+                File file = FileUtil.file(filePath);
+                if (!FileUtil.exist(file.getParent())) {
+                    FileUtil.mkdir(file.getParent());
+                }
+                File pathKeyFile = FileUtil.file(FdkkLaserConfig.getProfile() + File.separator + pathKey);
+                if (!FileUtil.exist(pathKeyFile.getParent())) {
+                    FileUtil.mkdir(pathKeyFile.getParent());
+                }
+                CmdBuildUtil.MkLinkFile(pathKeyFile.getAbsolutePath(), file.getAbsolutePath());
+            } else {
+                FileUtil.copy(filePath,
+                        FdkkLaserConfig.getProfile() + File.separator + pathKey,
+                        true);
+            }
+
+            return pathKey;
+        }
+    }
+
+
+    public File downloadFileTmp(String pathKey) {
+        if (FdkkLaserConfig.isLocalization()) {
+            return minioOssTemplate.downloadFileTmp(pathKey);
+        } else {
+            return aliyunOssTemplate.downloadFileTmp(pathKey);
+        }
+    }
+
+
+    public File downloadFileTmp(String bucket, String pathKey) {
+        if (FdkkLaserConfig.isLocalization()) {
+            return minioOssTemplate.downloadFileTmp(bucket, pathKey);
+        } else {
+            return aliyunOssTemplate.downloadFileTmp(bucket, pathKey);
+        }
+    }
+
+
+    public Object downloadFile(String pathKey, String file) {
+        if (FdkkLaserConfig.isLocalization()) {
+            return minioOssTemplate.downloadFile(pathKey, file);
+        } else {
+            return aliyunOssTemplate.downloadFile(pathKey, file);
+        }
+    }
+
+
+    public Object downloadFile(String bucket, String pathKey, String file) {
+        if (FdkkLaserConfig.isLocalization()) {
+            return minioOssTemplate.downloadFile(bucket, pathKey, file);
+        } else {
+            return aliyunOssTemplate.downloadFile(bucket, pathKey, file);
+        }
+    }
+
+
+    public Boolean copyObject(String oldPath, String newPath) {
+        if (FdkkLaserConfig.isLocalization()) {
+            return minioOssTemplate.copyObject(oldPath, newPath);
+        } else {
+            return aliyunOssTemplate.copyObject(oldPath, newPath);
+        }
+    }
+
+
+    public Boolean copyObject(String bucket, String oldPath, String toBucket, String newPath) {
+        if (FdkkLaserConfig.isLocalization()) {
+            return minioOssTemplate.copyObject(bucket, oldPath, toBucket, newPath);
+        } else {
+            return aliyunOssTemplate.copyObject(bucket, oldPath, toBucket, newPath);
+        }
+    }
+
+
+    public void deleteObject(String keyName) {
+        if (FdkkLaserConfig.isIsBucket()) {
+            if (FdkkLaserConfig.isLocalization()) {
+                minioOssTemplate.deleteObject(keyName);
+            } else {
+                aliyunOssTemplate.deleteObject(keyName);
+            }
+        } else {
+            FileUtil.del(
+                    FdkkLaserConfig.getProfile() + File.separator + keyName
+            );
+        }
+    }
+
+
+    public void deleteObject(String bucket, String keyName) {
+
+    }
+
+
+    public List<String> getFileFolder(String keyName) {
+        return null;
+    }
+
+
+    public List<String> getFileFolder(String bucket, String keyName) {
+        return null;
+    }
+
+
+    public boolean doesObjectExist(String bucket, String keyName) {
+        if (FdkkLaserConfig.isLocalization()) {
+            return minioOssTemplate.doesObjectExist(bucket, keyName);
+        } else {
+            return aliyunOssTemplate.doesObjectExist(bucket, keyName);
+        }
+    }
+
+
+    public boolean doesObjectExist(String keyName) {
+        if (FdkkLaserConfig.isIsBucket()) {
+            if (FdkkLaserConfig.isLocalization()) {
+                return minioOssTemplate.doesObjectExist(keyName);
+            } else {
+                return aliyunOssTemplate.doesObjectExist(keyName);
+            }
+        } else {
+            return FileUtil.exist(FdkkLaserConfig.getProfile() + File.separator + keyName);
+        }
+    }
+
+
+    public Object downloadFile(String bucket, String pathKey, Consumer handler) {
+        return null;
+    }
+
+
+    public Object downloadFile(String pathKey, Consumer handler) {
+        return null;
+    }
+
+    public String calculateUrl(String keyName) {
+        if (FdkkLaserConfig.isIsBucket()) {
+            if (FdkkLaserConfig.isLocalization()) {
+                return keyName;
+            } else {
+                return keyName;
+            }
+        } else {
+            return FdkkLaserConfig.getProfile() + File.separator + keyName;
+        }
+    }
+}

+ 47 - 0
src/main/java/com/fdkankan/scene/oss/aliyun/AliyunOssAutoConfiguration.java

@@ -0,0 +1,47 @@
+package com.fdkankan.scene.oss.aliyun;
+
+
+import com.aliyun.oss.OSS;
+import com.aliyun.oss.OSSClientBuilder;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import static com.fdkankan.scene.oss.aliyun.AliyunOssProperties.PREFIX;
+
+
+/**
+ * 阿里云OSS自动配置类
+ */
+@Configuration
+@ConditionalOnProperty(prefix = PREFIX, name = "enabled", havingValue = "true", matchIfMissing = true)
+@EnableAutoConfiguration
+public class AliyunOssAutoConfiguration {
+
+    @Bean
+    @ConditionalOnMissingBean
+    public OSS aliyunOssClient(AliyunOssProperties properties) {
+        return new OSSClientBuilder().build(properties.getRequestEndpoint(),
+                properties.getAccessKeyId(),
+                properties.getAccessKeySecret(),
+                properties.getConfig());
+    }
+
+    @Bean
+    @ConditionalOnMissingBean
+    @ConfigurationProperties(PREFIX)
+    public AliyunOssProperties aliyunOssProperties() {
+        return new AliyunOssProperties();
+    }
+
+
+    @Bean
+    @ConditionalOnMissingBean
+    public AliyunOssTemplate aliyunOssTemplate(OSS oss, AliyunOssProperties properties) {
+        return new AliyunOssTemplate(oss, properties);
+    }
+
+}

+ 100 - 0
src/main/java/com/fdkankan/scene/oss/aliyun/AliyunOssProperties.java

@@ -0,0 +1,100 @@
+package com.fdkankan.scene.oss.aliyun;
+
+
+import com.aliyun.oss.ClientBuilderConfiguration;
+import com.fdkankan.scene.oss.InnerUtils;
+import lombok.Data;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.util.StringUtils;
+
+import java.io.Serializable;
+import java.util.Map;
+
+/**
+ * 阿里云OSS配置属性
+ */
+@Data
+public class AliyunOssProperties implements Serializable, InitializingBean {
+
+    public static final String PREFIX = "aliyun.oss";
+
+    private String env;
+
+    /**
+     * 服务地址
+     */
+    private String endpoint;
+
+    /**
+     * 服务地址(内网)
+     */
+    private String internalEndpoint;
+
+    /**
+     * 区域id
+     */
+    private String regionId;
+
+    /**
+     * 访问标识
+     */
+    private String accessKeyId;
+
+    /**
+     * 访问密钥
+     */
+    private String accessKeySecret;
+
+    /**
+     * 会话token
+     */
+    private String securityToken;
+
+    /**
+     * 授权信息
+     */
+    private String roleArn;
+
+    /**
+     * 自定义域名, bucket名称忽略大小写
+     */
+    private Map<String, String> bucketCustomDomain;
+
+    /**
+     * Bucket
+     */
+    private String bucket;
+    /**
+     * Client configuration.
+     */
+    private ClientBuilderConfiguration config = new ClientBuilderConfiguration();
+
+    @Override
+    public void afterPropertiesSet() {
+        InnerUtils.checkArgument(!StringUtils.isEmpty(endpoint), "'endpoint' can't be empty");
+        InnerUtils.checkArgument(!StringUtils.isEmpty(bucket), "'bucket' can't be empty");
+    }
+
+    /**
+     * 获取请求到阿里云的服务地址, 内网地址优先
+     */
+    public String getRequestEndpoint() {
+        if (this.internalEndpoint != null && this.internalEndpoint.length() > 0) {
+            return internalEndpoint;
+        }
+        return endpoint;
+    }
+
+    /**
+     * 获取访问访问前缀, 优先级: customDomain > endpoint
+     */
+    public String getHostByBucket(String bucket) {
+        if (bucketCustomDomain != null) {
+            String domain = bucketCustomDomain.get(bucket);
+            if (domain != null && domain.length() > 0) {
+                return domain;
+            }
+        }
+        return InnerUtils.generateHost(this.endpoint, bucket);
+    }
+}

+ 292 - 0
src/main/java/com/fdkankan/scene/oss/aliyun/AliyunOssTemplate.java

@@ -0,0 +1,292 @@
+package com.fdkankan.scene.oss.aliyun;
+
+
+import cn.hutool.core.util.StrUtil;
+import com.alibaba.fastjson.JSON;
+import com.aliyun.oss.OSS;
+import com.aliyun.oss.model.*;
+import com.fdkankan.scene.constant.CmdConstant;
+import com.fdkankan.scene.oss.Consumer;
+import com.fdkankan.scene.oss.InnerUtils;
+import com.fdkankan.scene.oss.OssOptions;
+import com.fdkankan.scene.util.CmdUtils;
+import lombok.Getter;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.util.Base64Utils;
+import org.springframework.util.StringUtils;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+/**
+ * 阿里云操作模版类, 简化常见操作
+ */
+@Getter
+@Slf4j
+public class AliyunOssTemplate implements OssOptions<ObjectMetadata> {
+
+    private final OSS ossClient;
+    private final AliyunOssProperties ossProperties;
+
+    AliyunOssTemplate(OSS ossClient, AliyunOssProperties ossProperties) {
+        this.ossClient = ossClient;
+        this.ossProperties = ossProperties;
+    }
+
+    @Override
+    public void uploadFileChunkCmd(String defaultFolder, String sceneCode, String uploadDir, String targetDir, String mergeCode) {
+        String cmd = CmdConstant.OSSUTIL_UPLOAD_DIR_CHUNK;
+        cmd = cmd.replaceAll("@defaultFolder", defaultFolder);
+        cmd = cmd.replaceAll("@sceneCode", sceneCode);
+        cmd = cmd.replaceAll("@mergeCode", mergeCode);
+        cmd = cmd.replaceAll("@uploadDir", uploadDir);
+        cmd = cmd.replaceAll("@target", targetDir);
+        CmdUtils.ossUploadDir(cmd);
+
+    }
+
+    @Override
+    public void uploadFileDirCmd(String uploadDir, String target) {
+        String cmd = CmdConstant.OSSUTIL_UPLOAD_DIR;
+        cmd = cmd.replaceAll("@uploadDir", uploadDir);
+        cmd = cmd.replaceAll("@target", target);
+        CmdUtils.ossUploadDir(cmd);
+    }
+
+    @Override
+    public String uploadFile(String pathKey, String filePath) {
+        return uploadFile(ossProperties.getBucket(), pathKey, filePath);
+    }
+
+    @Override
+    public void rmFileCmd(String targetDir) {
+        String cmd = CmdConstant.OSSUTIL_RM_DIR;
+        cmd = cmd.replaceAll("@target", targetDir);
+        CmdUtils.ossDeleteDir(cmd);
+    }
+
+    @Override
+    public String uploadFile(String bucket, String pathKey, String filePath) {
+        InnerUtils.checkArgument(bucket != null && bucket.length() > 0, "bucket can't be empty");
+        InnerUtils.checkArgument(pathKey != null && pathKey.length() > 0, "pathKey can't be empty");
+        ObjectMetadata metadata = new ObjectMetadata();
+        ossClient.putObject(bucket, pathKey, new File(filePath), metadata);
+        return pathKey;
+    }
+
+    @Override
+    public String uploadFileText(String pathKey, String content) {
+        return uploadFileText(ossProperties.getBucket(), pathKey, content);
+    }
+
+    @Override
+    public String uploadFileText(String bucket, String pathKey, String content) {
+        byte[] bytes = content.getBytes(StandardCharsets.UTF_8);
+        return uploadFileBytes(bucket, pathKey, bytes);
+    }
+
+    @Override
+    public String uploadFileBase64Image(String pathKey, String content) {
+        return uploadFileBase64Image(ossProperties.getBucket(), pathKey, content);
+    }
+
+    @Override
+    public String uploadFileBase64Image(String bucket, String pathKey, String content) {
+        byte[] bytes = Base64Utils.decodeFromString(content);
+        return uploadFileBytes(bucket, pathKey, bytes);
+    }
+
+    @Override
+    public String uploadFileBytes(String pathKey, byte[] bytes) {
+        return uploadFileBytes(ossProperties.getBucket(), pathKey, bytes);
+    }
+
+    @Override
+    public String uploadFileBytes(String bucket, String pathKey, byte[] bytes) {
+        ByteArrayInputStream stream = new ByteArrayInputStream(bytes);
+        return uploadFileStream(bucket, pathKey, stream);
+    }
+
+    @Override
+    public String uploadFileStream(String pathKey, InputStream stream) {
+        return uploadFileStream(ossProperties.getBucket(), pathKey, stream);
+    }
+
+    @Override
+    public String uploadFileStream(String bucket, String pathKey, InputStream stream) {
+        InnerUtils.checkArgument(bucket != null && bucket.length() > 0, "bucket can't be empty");
+        InnerUtils.checkArgument(pathKey != null && pathKey.length() > 0, "pathKey can't be empty");
+        InnerUtils.checkArgument(stream != null, "stream can't be null");
+
+        ObjectMetadata metadata = new ObjectMetadata();
+        ossClient.putObject(bucket, pathKey, stream, metadata);
+        return pathKey;
+    }
+
+    @Override
+    public File downloadFileTmp(String pathKey) {
+        return downloadFileTmp(ossProperties.getBucket(), pathKey);
+    }
+
+    @Override
+    public File downloadFileTmp(String bucket, String pathKey) {
+        String tmpDir = System.getProperty("java.io.tmpdir");
+        String file = tmpDir + UUID.randomUUID();
+        downloadFile(bucket, pathKey, file);
+        return new File(file);
+    }
+
+    @Override
+    public ObjectMetadata downloadFile(String pathKey, String file) {
+        return downloadFile(ossProperties.getBucket(), pathKey, file);
+    }
+
+    @Override
+    public ObjectMetadata downloadFile(String bucket, String pathKey, String file) {
+        InnerUtils.checkArgument(bucket != null && bucket.length() > 0, "bucket can't be empty");
+        InnerUtils.checkArgument(pathKey != null && pathKey.length() > 0, "pathKey can't be empty");
+        InnerUtils.checkArgument(file != null && file.length() > 0, "file can't be empty");
+        GetObjectRequest request = new GetObjectRequest(bucket, pathKey);
+        AliyunOssTemplate.log.info("下载开始:下载bucket={},下载pathKey={},下载filePath={}", bucket, pathKey, file);
+        return ossClient.getObject(request, new File(file));
+    }
+
+    @Override
+    public ObjectMetadata downloadFile(String pathKey, Consumer<InputStream> handler) {
+        return downloadFile(ossProperties.getBucket(), pathKey, handler);
+    }
+
+    @Override
+    public ObjectMetadata downloadFile(String bucket, String pathKey, Consumer<InputStream> handler) {
+        InnerUtils.checkArgument(bucket != null && bucket.length() > 0, "bucket can't be empty");
+        InnerUtils.checkArgument(pathKey != null && pathKey.length() > 0, "pathKey can't be empty");
+        InnerUtils.checkArgument(handler != null, "handler can't be null");
+        OSSObject ossObject = ossClient.getObject(bucket, pathKey);
+        InputStream content = ossObject.getObjectContent();
+        try {
+            handler.accept(content);
+        } finally {
+            if (content != null) {
+                try {
+                    content.close();
+                } catch (IOException e) {
+                    // Ignore
+                }
+            }
+        }
+        return ossObject.getObjectMetadata();
+    }
+
+    public String calculateUrl(String pathKey) {
+        return pathKey;
+    }
+
+    public String calculateUrl(String bucket, String pathKey) {
+        String host = ossProperties.getHostByBucket(bucket);
+        return host + "/" + pathKey;
+    }
+
+    public String calculatePathKey(String url) {
+        String urlPath = InnerUtils.getUrlPath(url);
+        if (urlPath != null && urlPath.startsWith("/")) {
+            String pathKey = urlPath.substring(1);
+            if (pathKey.length() > 0) {
+                return InnerUtils.decodeUrl(pathKey);
+            }
+        }
+        return null;
+    }
+
+    public String calculateHost(String endpoint, String bucket) {
+        return InnerUtils.generateHost(endpoint, bucket);
+    }
+
+
+    @Override
+    public Boolean copyObject(String oldPath, String newPath) {
+        return copyObject(ossProperties.getBucket(), oldPath, ossProperties.getBucket(), newPath);
+    }
+
+    @Override
+    public Boolean copyObject(String bucket, String oldPath, String toBucket, String newPath) {
+        AliyunOssTemplate.log.info("拷贝开始:oldBucket={},oldPath={},newBucket={},newPath={}", bucket, oldPath, toBucket, newPath);
+        String versionId = ossClient.copyObject(bucket, oldPath, toBucket, newPath).getVersionId();
+        return StrUtil.isNotBlank(versionId);
+    }
+
+    @Override
+    public void deleteObject(String keyName) {
+        if (!doesObjectExist(keyName)) {
+            deleteObject(ossProperties.getBucket(), keyName);
+        } else {
+            AliyunOssTemplate.log.warn("文件不存在,KeyName{}", keyName);
+        }
+    }
+
+    @Override
+    public void deleteObject(String bucket, String keyName) {
+        ossClient.deleteObject(bucket, keyName);
+    }
+
+    @Override
+    public List<String> getFileFolder(String keyName) {
+        return getFileFolder(ossProperties.getBucket(), keyName);
+    }
+
+    @Override
+    public List<String> getFileFolder(String bucket, String keyName) {
+        ListObjectsRequest listObjectsRequest = new ListObjectsRequest(ossProperties.getBucket());
+        // 设置正斜线(/)为文件夹的分隔符。
+        listObjectsRequest.setDelimiter("/");
+        // 设置prefix参数来获取fun目录下的所有文件。
+        if (!StringUtils.isEmpty(keyName)) {
+            listObjectsRequest.setPrefix(keyName + "/");
+        }
+        ObjectListing listing = ossClient.listObjects(listObjectsRequest);
+        // 遍历所有commonPrefix
+        List<String> list = new ArrayList<>();
+        for (OSSObjectSummary objectSummary : listing.getObjectSummaries()) {
+            list.add(objectSummary.getKey());
+        }
+        AliyunOssTemplate.log.info("获取文件夹集合={}", JSON.toJSONString(list));
+        return list;
+    }
+
+    @Override
+    public boolean doesObjectExist(String bucket, String keyName) {
+        boolean b = ossClient.doesObjectExist(bucket, keyName);
+        AliyunOssTemplate.log.info("文件是否存在={}", b);
+        return b;
+    }
+
+    @Override
+    public boolean doesObjectExist(String keyName) {
+        return doesObjectExist(ossProperties.getBucket(), keyName);
+    }
+
+    @Override
+    public String uploadFileImage(String pathKey, String filePath) {
+        return uploadFileImage(ossProperties.getBucket(), pathKey, filePath);
+    }
+
+    @Override
+    public String uploadFileImage(String bucket, String pathKey, String filePath) {
+        ObjectMetadata metadata = new ObjectMetadata();
+        if (filePath.contains(".jpg")) {
+            metadata.setContentType("image/jpeg");
+        } else if (filePath.contains(".png")) {
+            metadata.setContentType("image/png");
+        }
+        AliyunOssTemplate.log.info("上传开始:上传bucket={},上传pathKey={},上传filePath={}", bucket, pathKey, filePath);
+        ossClient.putObject(bucket, pathKey, new File(filePath), metadata);
+        return calculateUrl(bucket, pathKey);
+    }
+
+
+}

+ 46 - 0
src/main/java/com/fdkankan/scene/oss/minio/MinioOssAutoConfiguration.java

@@ -0,0 +1,46 @@
+package com.fdkankan.scene.oss.minio;
+
+
+import io.minio.MinioClient;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import static com.fdkankan.scene.oss.minio.MinioOssProperties.PREFIX;
+
+
+/**
+ * 阿里云OSS自动配置类
+ */
+@Configuration
+@ConditionalOnProperty(prefix = PREFIX, name = "enabled", havingValue = "true", matchIfMissing = true)
+@EnableAutoConfiguration
+public class MinioOssAutoConfiguration {
+
+    @Bean
+    @ConditionalOnMissingBean
+    public MinioClient minioClient(MinioOssProperties properties) {
+        return MinioClient.builder()
+                .endpoint(properties.getMinioUrl())
+                .credentials(properties.getMinioName(), properties.getMinioPass())
+                .build();
+    }
+
+    @Bean
+    @ConditionalOnMissingBean
+    @ConfigurationProperties(PREFIX)
+    public MinioOssProperties MinioOssProperties() {
+        return new MinioOssProperties();
+    }
+
+
+    @Bean
+    @ConditionalOnMissingBean
+    public MinioOssTemplate minioOssTemplate(MinioClient oss, MinioOssProperties properties) {
+        return new MinioOssTemplate(oss, properties);
+    }
+
+}

+ 70 - 0
src/main/java/com/fdkankan/scene/oss/minio/MinioOssProperties.java

@@ -0,0 +1,70 @@
+package com.fdkankan.scene.oss.minio;
+
+
+import com.aliyun.oss.ClientBuilderConfiguration;
+import com.fdkankan.scene.oss.InnerUtils;
+import lombok.Data;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.util.StringUtils;
+
+import java.io.Serializable;
+import java.util.Map;
+
+/**
+ * MinioOSS配置属性
+ */
+@Data
+public class MinioOssProperties implements Serializable, InitializingBean {
+
+    public static final String PREFIX = "minio.oss";
+
+    private String env;
+    private String minioUrl;
+    private String minioName;
+    private String minioPass;
+    /**
+     * 服务地址(内网)
+     */
+    private String internalMinioUrl;
+    /**
+     * 自定义域名, bucket名称忽略大小写
+     */
+    private Map<String, String> bucketCustomDomain;
+    /**
+     * Bucket
+     */
+    private String bucket;
+    /**
+     * Client configuration.
+     */
+    private ClientBuilderConfiguration config = new ClientBuilderConfiguration();
+
+    @Override
+    public void afterPropertiesSet() {
+        InnerUtils.checkArgument(!StringUtils.isEmpty(minioUrl), "'minioUrl' can't be empty");
+        InnerUtils.checkArgument(!StringUtils.isEmpty(bucket), "'bucket' can't be empty");
+    }
+
+    /**
+     * 获取请求到Minio的服务地址, 内网地址优先
+     */
+    public String getRequestEndpoint() {
+        if (this.internalMinioUrl != null && this.internalMinioUrl.length() > 0) {
+            return internalMinioUrl;
+        }
+        return minioUrl;
+    }
+
+    /**
+     * 获取访问访问前缀, 优先级: customDomain > endpoint
+     */
+    public String getHostByBucket(String bucket) {
+        if (bucketCustomDomain != null) {
+            String domain = bucketCustomDomain.get(bucket);
+            if (domain != null && domain.length() > 0) {
+                return domain;
+            }
+        }
+        return InnerUtils.generateHost(this.minioUrl, bucket);
+    }
+}

+ 361 - 0
src/main/java/com/fdkankan/scene/oss/minio/MinioOssTemplate.java

@@ -0,0 +1,361 @@
+package com.fdkankan.scene.oss.minio;
+
+
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.io.IoUtil;
+import cn.hutool.core.util.StrUtil;
+import com.alibaba.fastjson.JSON;
+import com.fdkankan.scene.constant.CmdConstant;
+import com.fdkankan.scene.oss.Consumer;
+import com.fdkankan.scene.oss.InnerUtils;
+import com.fdkankan.scene.oss.OssOptions;
+import com.fdkankan.scene.util.CmdUtils;
+import io.minio.*;
+import io.minio.errors.ErrorResponseException;
+import io.minio.messages.Item;
+import lombok.Getter;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.util.Base64Utils;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+/**
+ * 阿里云操作模版类, 简化常见操作
+ */
+@Getter
+@Slf4j
+public class MinioOssTemplate implements OssOptions<GetObjectResponse> {
+
+    private final MinioClient minioClient;
+    private final MinioOssProperties ossProperties;
+
+    MinioOssTemplate(MinioClient minioClient, MinioOssProperties ossProperties) {
+        this.minioClient = minioClient;
+        this.ossProperties = ossProperties;
+    }
+
+    @Override
+    public void uploadFileChunkCmd(String defaultFolder, String sceneCode, String uploadDir, String targetDir, String mergeCode) {
+        String cmd = CmdConstant.MINIO_OSSUTIL_UPLOAD_DIR_CHUNK;
+        cmd = cmd.replaceAll("@defaultFolder", defaultFolder);
+        cmd = cmd.replaceAll("@sceneCode", sceneCode);
+        cmd = cmd.replaceAll("@mergeCode", mergeCode);
+        cmd = cmd.replaceAll("@uploadDir", uploadDir);
+//        cmd = cmd.replaceAll("@target", targetDir);
+        CmdUtils.ossUploadDir(cmd);
+
+    }
+
+    @Override
+    public void uploadFileDirCmd(String uploadDir, String target) {
+        String cmd = CmdConstant.MINIO_UTIL_UPLOAD_DIR;
+        cmd = cmd.replaceAll("@uploadDir", uploadDir);
+        cmd = cmd.replaceAll("@target", target);
+        CmdUtils.ossUploadDir(cmd);
+    }
+
+    @Override
+    public void rmFileCmd(String targetDir) {
+        String cmd = CmdConstant.MINIO_UTIL_RM_DIR;
+        cmd = cmd.replaceAll("@target", targetDir);
+        CmdUtils.ossDeleteDir(cmd);
+    }
+
+    @Override
+    public String uploadFile(String pathKey, String filePath) {
+        return uploadFile(ossProperties.getBucket(), pathKey, filePath);
+    }
+
+    @Override
+    public String uploadFile(String bucket, String pathKey, String filePath) {
+        InnerUtils.checkArgument(bucket != null && bucket.length() > 0, "bucket can't be empty");
+        InnerUtils.checkArgument(pathKey != null && pathKey.length() > 0, "pathKey can't be empty");
+        uploadFileStream(bucket, pathKey, FileUtil.getInputStream(new File(filePath)));
+        return pathKey;
+    }
+
+    @Override
+    public String uploadFileText(String pathKey, String content) {
+        return uploadFileText(ossProperties.getBucket(), pathKey, content);
+    }
+
+    @Override
+    public String uploadFileText(String bucket, String pathKey, String content) {
+        byte[] bytes = content.getBytes(StandardCharsets.UTF_8);
+        return uploadFileBytes(bucket, pathKey, bytes);
+    }
+
+    @Override
+    public String uploadFileBase64Image(String pathKey, String content) {
+        return uploadFileBase64Image(ossProperties.getBucket(), pathKey, content);
+    }
+
+    @Override
+    public String uploadFileBase64Image(String bucket, String pathKey, String content) {
+        byte[] bytes = Base64Utils.decodeFromString(content);
+        return uploadFileBytes(bucket, pathKey, bytes);
+    }
+
+    @Override
+    public String uploadFileBytes(String pathKey, byte[] bytes) {
+        return uploadFileBytes(ossProperties.getBucket(), pathKey, bytes);
+    }
+
+    public void createbucket() {
+        try {
+            minioClient.makeBucket(MakeBucketArgs.builder().bucket(ossProperties.getBucket()).build());
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    @Override
+    public String uploadFileBytes(String bucket, String pathKey, byte[] bytes) {
+        ByteArrayInputStream stream = new ByteArrayInputStream(bytes);
+        return uploadFileStream(bucket, pathKey, stream);
+    }
+
+    @Override
+    public String uploadFileStream(String pathKey, InputStream stream) {
+        return uploadFileStream(ossProperties.getBucket(), pathKey, stream);
+    }
+
+    @Override
+    public String uploadFileStream(String bucket, String pathKey, InputStream stream) {
+
+        InnerUtils.checkArgument(bucket != null && bucket.length() > 0, "bucket can't be empty");
+        InnerUtils.checkArgument(pathKey != null && pathKey.length() > 0, "pathKey can't be empty");
+        InnerUtils.checkArgument(stream != null, "stream can't be null");
+        try {
+            String contentType = "application/octet-stream";
+            if (pathKey.contains(".jpg")) {
+                contentType = ("image/jpeg");
+            } else if (pathKey.contains(".png")) {
+                contentType = ("image/png");
+            } else if (pathKey.contains(".json")) {
+                contentType = ("application/json");
+            }
+            PutObjectArgs objectArgs = PutObjectArgs.builder().object(pathKey)
+                    .bucket(bucket)
+                    .contentType(contentType)
+                    .stream(stream, stream.available(), -1).build();
+            ObjectWriteResponse objectWriteResponse = minioClient.putObject(objectArgs);
+            MinioOssTemplate.log.info(objectWriteResponse.object());
+
+        } catch (Exception e) {
+            MinioOssTemplate.log.error(e.getMessage(), e);
+        }
+        return pathKey;
+    }
+
+    @Override
+    public File downloadFileTmp(String pathKey) {
+        return downloadFileTmp(ossProperties.getBucket(), pathKey);
+    }
+
+    @Override
+    public File downloadFileTmp(String bucket, String pathKey) {
+        String tmpDir = System.getProperty("java.io.tmpdir");
+        String file = tmpDir + UUID.randomUUID();
+        downloadFile(bucket, pathKey, file);
+        return new File(file);
+    }
+
+    @Override
+    public GetObjectResponse downloadFile(String pathKey, String file) {
+        return downloadFile(ossProperties.getBucket(), pathKey, file);
+    }
+
+    @Override
+    public GetObjectResponse downloadFile(String bucket, String pathKey, String file) {
+        InnerUtils.checkArgument(bucket != null && bucket.length() > 0, "bucket can't be empty");
+        InnerUtils.checkArgument(pathKey != null && pathKey.length() > 0, "pathKey can't be empty");
+        InnerUtils.checkArgument(file != null && file.length() > 0, "file can't be empty");
+        GetObjectArgs objectArgs = GetObjectArgs.builder().object(pathKey)
+                .bucket(bucket).build();
+        MinioOssTemplate.log.info("下载开始:下载bucket={},下载pathKey={},下载filePath={}", bucket, pathKey, file);
+        try {
+            return minioClient.getObject(objectArgs);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    @Override
+    public GetObjectResponse downloadFile(String pathKey, Consumer<InputStream> handler) {
+        return downloadFile(ossProperties.getBucket(), pathKey, handler);
+    }
+
+    @Override
+    public GetObjectResponse downloadFile(String bucket, String pathKey, Consumer<InputStream> handler) {
+        InnerUtils.checkArgument(bucket != null && bucket.length() > 0, "bucket can't be empty");
+        InnerUtils.checkArgument(pathKey != null && pathKey.length() > 0, "pathKey can't be empty");
+        InnerUtils.checkArgument(handler != null, "handler can't be null");
+        GetObjectArgs objectArgs = GetObjectArgs.builder().object(pathKey)
+                .bucket(bucket).build();
+        GetObjectResponse ossObject = null;
+        try {
+            ossObject = minioClient.getObject(objectArgs);
+            return ossObject;
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return null;
+    }
+
+    public String calculateUrl(String pathKey) {
+        return pathKey;
+    }
+
+    public String calculateUrl(String bucket, String pathKey) {
+        String host = ossProperties.getHostByBucket(bucket);
+        return host + "/" + bucket + "/" + pathKey;
+    }
+
+    public String calculatePathKey(String url) {
+        String urlPath = InnerUtils.getUrlPath(url);
+        if (urlPath != null && urlPath.startsWith("/")) {
+            String pathKey = urlPath.substring(1);
+            if (pathKey.length() > 0) {
+                return InnerUtils.decodeUrl(pathKey);
+            }
+        }
+        return null;
+    }
+
+    public String calculateHost(String endpoint, String bucket) {
+        return InnerUtils.generateHost(endpoint, bucket);
+    }
+
+
+    @Override
+    public Boolean copyObject(String oldPath, String newPath) {
+        return copyObject(ossProperties.getBucket(), oldPath, ossProperties.getBucket(), newPath);
+    }
+
+    @Override
+    public Boolean copyObject(String bucket, String oldPath, String toBucket, String newPath) {
+        try {
+            ObjectWriteResponse response = minioClient.copyObject(CopyObjectArgs.builder()
+                    .source(CopySource.builder().bucket(bucket).object(oldPath).build())
+                    .bucket(toBucket)
+                    .object(newPath)
+                    .build());
+            return StrUtil.isNotBlank(response.versionId());
+        } catch (Exception e) {
+            MinioOssTemplate.log.error("文件不存在,KeyName{}", e.getMessage());
+            return false;
+        }
+    }
+
+    @Override
+    public void deleteObject(String keyName) {
+        if (!doesObjectExist(keyName)) {
+            deleteObject(ossProperties.getBucket(), keyName);
+        } else {
+            MinioOssTemplate.log.warn("文件不存在,KeyName{}", keyName);
+        }
+    }
+
+    @Override
+    public void deleteObject(String bucket, String keyName) {
+        try {
+            RemoveObjectArgs objectArgs = RemoveObjectArgs.builder().object(keyName)
+                    .bucket(bucket).build();
+            minioClient.removeObject(objectArgs);
+        } catch (Exception e) {
+            MinioOssTemplate.log.info("文件删除失败" + e.getMessage());
+        }
+    }
+
+    @Override
+    public List<String> getFileFolder(String keyName) {
+        return getFileFolder(ossProperties.getBucket(), keyName);
+    }
+
+    @Override
+    public List<String> getFileFolder(String bucket, String keyName) {
+        List<String> list = new ArrayList<>();
+        try {
+            ListObjectsArgs objectArgs = ListObjectsArgs.builder()
+                    .bucket(bucket).recursive(true).prefix(keyName + "/").build();
+            Iterable<Result<Item>> results = minioClient.listObjects(objectArgs);
+            for (Result<Item> result : results) {
+                Item item = result.get();
+                list.add(item.objectName());
+            }
+            MinioOssTemplate.log.info("获取文件夹集合={}", JSON.toJSONString(list));
+        } catch (Exception e) {
+            MinioOssTemplate.log.error("获取文件夹集合失败={}", e.getMessage());
+        }
+
+        return list;
+    }
+
+    @Override
+    public boolean doesObjectExist(String bucket, String keyName) {
+        GetObjectArgs getArgs = GetObjectArgs.builder()
+                .bucket(bucket)
+                .object(keyName)
+                .build();
+        try {
+            GetObjectResponse response = minioClient.getObject(getArgs);
+            return true;
+        } catch (ErrorResponseException e) {
+            if (e.errorResponse().code().equals("NoSuchKey")) {
+                return false;
+            }
+            MinioOssTemplate.log.error("NoSuchKey", e.getMessage());
+        } catch (Exception e) {
+            MinioOssTemplate.log.error("连接异常", e.getMessage());
+            return false;
+        }
+        return false;
+    }
+
+    @Override
+    public boolean doesObjectExist(String keyName) {
+        return doesObjectExist(ossProperties.getBucket(), keyName);
+    }
+
+    @Override
+    public String uploadFileImage(String pathKey, String filePath) {
+        return uploadFileImage(ossProperties.getBucket(), pathKey, filePath);
+    }
+
+    @Override
+    public String uploadFileImage(String bucket, String pathKey, String filePath) {
+        InputStream stream = null;
+        try {
+            String contentType = "application/octet-stream";
+            if (filePath.contains(".jpg")) {
+                contentType = ("image/jpeg");
+            } else if (filePath.contains(".png")) {
+                contentType = ("image/png");
+            } else if (filePath.contains(".json")) {
+                contentType = ("application/json");
+            }
+            stream = FileUtil.getInputStream(new File(filePath));
+            PutObjectArgs objectArgs = PutObjectArgs.builder().object(pathKey)
+                    .bucket(bucket)
+                    .contentType(contentType)
+                    .stream(stream, stream.available(), -1).build();
+            MinioOssTemplate.log.info("上传开始:上传bucket={},上传pathKey={},上传filePath={}", bucket, pathKey, filePath);
+            ObjectWriteResponse objectWriteResponse = minioClient.putObject(objectArgs);
+        } catch (Exception e) {
+            return "";
+        } finally {
+            IoUtil.close(stream);
+        }
+        return pathKey;
+    }
+
+
+}

+ 2 - 1
src/main/java/com/fdkankan/scene/service/impl/SceneEditInfoServiceImpl.java

@@ -95,6 +95,8 @@ import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.multipart.MultipartFile;
 
+import javax.annotation.Resource;
+
 /**
  * <p>
  *  服务实现类
@@ -134,7 +136,6 @@ public class SceneEditInfoServiceImpl extends ServiceImpl<ISceneEditInfoMapper,
     private ICameraDetailService cameraDetailService;
     @Autowired
     private ICompanyService companyService;
-
     @Transactional
     @Override
     public SceneEditInfoVO saveScene(SceneEditInfoParamVO param) {

+ 1 - 1
src/main/java/com/fdkankan/scene/service/impl/SceneUploadServiceImpl.java

@@ -143,7 +143,7 @@ public class SceneUploadServiceImpl extends ServiceImpl<ISceneUploadMapper, Scen
             String ossPath = StrUtil.isNotBlank(uploadPath) ? uploadPath : (String.format(UploadFilePath.USER_EDIT_PATH ,num) + realFileName);
             try {
 // TODO: 2022/8/22
-                //                fYunFileService.uploadFile(bucket, newFile.getPath(), ossPath);
+//                                fYunFileService.uploadFile(bucket, newFile.getPath(), ossPath);
             }catch (Exception e){
                 log.error(ossPath+"上传文件失败"+e);
                 throw new BusinessException(ErrorCode.FAILURE_CODE_7013);

+ 292 - 0
src/main/java/com/fdkankan/scene/util/CmdBuildUtil.java

@@ -0,0 +1,292 @@
+package com.fdkankan.scene.util;
+
+import cn.hutool.core.io.FileUtil;
+import cn.hutool.core.util.StrUtil;
+import cn.hutool.core.util.XmlUtil;
+import cn.hutool.core.util.ZipUtil;
+import cn.hutool.extra.spring.SpringUtil;
+import cn.hutool.system.OsInfo;
+import cn.hutool.system.SystemUtil;
+import com.alibaba.fastjson.JSONObject;
+import com.fdkankan.common.util.FileUtils;
+import com.fdkankan.scene.config.FdkkLaserConfig;
+import com.fdkankan.scene.constant.CmdConstant;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Component;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * 判断是否是单机。然后调用bat或者shell
+ *
+ * @author Xiewj
+ * @date 2022/6/8
+ */
+@Slf4j
+@Component
+public class CmdBuildUtil {
+
+    private static final OsInfo OS = SystemUtil.getOsInfo();
+    private static final FdkkLaserConfig fdkkLaserConfig = SpringUtil.getBean(FdkkLaserConfig.class);
+
+    public static void objTOGlb(String inPath, String outPath) {
+
+        String cp_folder = "";
+        if (CmdBuildUtil.OS.isLinux()) {
+            cp_folder = CmdConstant.OBJ_TO_GLB
+                    .replace("@inPath", inPath)
+                    .replace("@outPath", outPath);
+            CmdUtils.callLineSh(cp_folder);
+
+        } else {
+            cp_folder = CmdConstant.OBJ_TO_GLB_WIN
+                    .replace("@inPath", inPath)
+                    .replace("@outPath", outPath);
+            CmdUtils.callLine(cp_folder);
+        }
+    }
+
+    public static void DeleteFolder(String folder) {
+        String rm_folder = "";
+        if (CmdBuildUtil.OS.isLinux()) {
+            rm_folder = CmdConstant.RM_Folder.replace("@Folder", folder);
+            CmdUtils.callLineSh(rm_folder);
+
+        } else {
+            rm_folder = CmdConstant.RM_Folder_WIN.replace("@Folder", folder);
+            CmdUtils.callLine(rm_folder);
+        }
+    }
+
+    public static void MoveFolder(String folder, String target) {
+        String mv_folder = "";
+        if (CmdBuildUtil.OS.isLinux()) {
+            mv_folder = CmdConstant.MV_Folder
+                    .replace("@Folder", folder)
+                    .replace("@Target", target);
+            CmdUtils.callLineSh(mv_folder);
+
+        } else {
+            mv_folder = CmdConstant.MV_Folder_WIN
+                    .replace("@Folder", folder)
+                    .replace("@Target", target);
+            CmdUtils.callLine(mv_folder);
+        }
+    }
+
+    public static void CopyFolder(String folder, String target) {
+        String cp_folder = "";
+        if (CmdBuildUtil.OS.isLinux()) {
+            cp_folder = CmdConstant.CP_Folder
+                    .replace("@Folder", folder)
+                    .replace("@Target", target);
+            CmdUtils.callLineSh(cp_folder);
+
+        } else {
+            cp_folder = CmdConstant.CP_Folder_WIN
+                    .replace("@Folder", folder)
+                    .replace("@Target", target);
+            CmdUtils.callLine(cp_folder);
+        }
+    }
+
+    public static void MkLinkDir(String Link, String target) {
+        String cp_folder = "";
+        if (CmdBuildUtil.OS.isLinux()) {
+            cp_folder = CmdConstant.MK_LINK_DIR
+                    .replace("@Link", Link)
+                    .replace("@Target", target);
+            CmdUtils.callLineSh(cp_folder);
+
+        } else {
+            cp_folder = CmdConstant.MK_LINK_DIR_WIN
+                    .replace("@Link", Link)
+                    .replace("@Target", target);
+            CmdUtils.callLineWin(cp_folder);
+        }
+    }
+
+    public static void MkLinkFile(String Link, String target) {
+        String cp_folder = "";
+        if (CmdBuildUtil.OS.isLinux()) {
+            cp_folder = CmdConstant.MK_LINK_FILE
+                    .replace("@Link", Link)
+                    .replace("@Target", target);
+            CmdUtils.callLineSh(cp_folder);
+
+        } else {
+            cp_folder = CmdConstant.MK_LINK_FILE_WIN
+                    .replace("@Link", Link)
+                    .replace("@Target", target);
+            CmdUtils.callLineWin(cp_folder);
+        }
+    }
+
+    public static void ZipFile(String path, String target, String inPath) {
+        String zipCmd = "";
+        if (CmdBuildUtil.OS.isLinux()) {
+            zipCmd = CmdConstant.ZIP
+                    .replace("@path", path)
+                    .replace("@target", target)
+                    .replace("@inPath", inPath);
+            if (StrUtil.isNotEmpty(zipCmd)) {
+                CmdUtils.callLineSh(zipCmd);
+            }
+        } else {
+            ZipUtil.zip(path + File.separator + inPath, target, false);
+        }
+    }
+
+    public static void MergeCutModel(String inPath, String outPath) {
+        String mergeCutModelCmd = "";
+        if (CmdBuildUtil.OS.isLinux()) {
+            mergeCutModelCmd = CmdConstant.MERGE_CUT_MODEL
+                    .replace("@inPath", inPath)
+                    .replace("@outPath", outPath);
+            CmdUtils.callLineSh(mergeCutModelCmd);
+
+        } else {
+            mergeCutModelCmd = CmdConstant.MERGE_CUT_MODEL_WIN
+                    .replace("@inPath", inPath)
+                    .replace("@outPath", outPath);
+            CmdUtils.callLine(mergeCutModelCmd);
+        }
+
+    }
+
+    public static void ConverterAddGeo(String param, String inPath, String outPath) {
+        String converterAddGeoCmd = "";
+        if (CmdBuildUtil.OS.isLinux()) {
+            converterAddGeoCmd = CmdConstant.CONVERTER_ADD_GEO
+                    .replace("@param", param)
+                    .replace("@inPath", inPath)
+                    .replace("@outPath", outPath);
+            CmdUtils.callLineSh(converterAddGeoCmd);
+
+        } else {
+            converterAddGeoCmd = CmdConstant.CONVERTER_ADD_GEO_WIN
+                    .replace("@param", param)
+                    .replace("@inPath", inPath)
+                    .replace("@outPath", outPath);
+            CmdUtils.callLine(converterAddGeoCmd);
+
+        }
+
+    }
+
+    static void BuildModelCommand(String inPath) {
+        String buildModelCommandCmd = "";
+        if (CmdBuildUtil.OS.isLinux()) {
+            buildModelCommandCmd = CmdConstant.BUILD_MODEL_COMMAND
+                    .replace("@inPath", inPath);
+            CmdUtils.callLineSh(buildModelCommandCmd);
+
+        } else {
+            buildModelCommandCmd = CmdConstant.BUILD_MODEL_COMMAND_WIN
+                    .replace("@inPath", inPath);
+            CmdUtils.callLine(buildModelCommandCmd);
+
+        }
+
+    }
+
+    static void KillBuildModelCommand() {
+        String buildModelCommandCmd = "";
+        if (CmdBuildUtil.OS.isLinux()) {
+            buildModelCommandCmd = CmdConstant.KILL_BUILD_MODEL_COMMAND;
+            CmdUtils.callLineSh(buildModelCommandCmd);
+
+        } else {
+            buildModelCommandCmd = CmdConstant.KILL_BUILD_MODEL_COMMAND_WIN;
+            CmdUtils.callLine(buildModelCommandCmd);
+
+        }
+    }
+
+    public static Node License() throws IOException, InterruptedException {
+        String authLicenseCommandCmd = "";
+        String licensePath = CmdBuildUtil.fdkkLaserConfig.buildCallPath + File.separator + "license" + File.separator;
+        File caches = new File(licensePath + "caches");
+        FileUtil.del(caches);
+        File results = new File(licensePath + "results");
+        FileUtil.del(results);
+
+        JSONObject licenseDataJson = new JSONObject();
+        licenseDataJson.put("split_type", "SPLIT_V23");
+        licenseDataJson.put("skybox_type", "SKYBOX_V5");
+        FileUtils.writeFile(licensePath + File.separator + "data.json", licenseDataJson.toString());
+        if (CmdBuildUtil.OS.isLinux()) {
+            authLicenseCommandCmd = CmdConstant.AUTH_LICENSE_WIN;
+            CmdUtils.callLineSh(authLicenseCommandCmd);
+        } else {
+            authLicenseCommandCmd = CmdConstant.AUTH_LICENSE_WIN
+                    .replace("@inPath", licensePath);
+            CmdUtils.callLine(authLicenseCommandCmd);
+        }
+        int count = 10;
+        try {
+            for (int i = count; i > 0; i--) {
+                if (FileUtil.exist(licensePath + File.separator + "results" + File.separator + "encryption_info.xml")) {
+                    Document document = XmlUtil.readXML(licensePath + File.separator + "results" + File.separator + "encryption_info.xml");
+                    return XmlUtil.getNodeByXPath("//licenseInfo//snInfo", document);
+                }
+                Thread.sleep(1000);
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            return null;
+        }
+        return null;
+    }
+
+    public static void TiledMap(String inPath) {
+        String tiledMapCmd = "";
+        if (CmdBuildUtil.OS.isLinux()) {
+            tiledMapCmd = CmdConstant.TILED_MAP
+                    .replace("@inPath", inPath);
+            CmdUtils.callLineSh(tiledMapCmd);
+
+        } else {
+            tiledMapCmd = CmdConstant.TILED_MAP_WIN
+                    .replace("@inPath", inPath);
+            CmdUtils.callLine(tiledMapCmd);
+        }
+
+    }
+
+    public static void LasToBin(String inPath, String outPath) {
+        String lasToBinCmd = "";
+        if (CmdBuildUtil.OS.isLinux()) {
+            lasToBinCmd = CmdConstant.LAS_TO_BIN
+                    .replace("@inPath", inPath)
+                    .replace("@outPath", outPath);
+            CmdUtils.callLineSh(lasToBinCmd);
+
+        } else {
+            lasToBinCmd = CmdConstant.LAS_TO_BIN_WIN
+                    .replace("@inPath", inPath)
+                    .replace("@outPath", outPath);
+            CmdUtils.callLine(lasToBinCmd);
+        }
+    }
+
+    public static void CheckLaser(String inPath, String outPath) {
+        String checkLaserCmd = "";
+        if (CmdBuildUtil.OS.isLinux()) {
+            checkLaserCmd = CmdConstant.CHECK_LASER
+                    .replace("@inPath", inPath)
+                    .replace("@outPath", outPath);
+            CmdUtils.callLineSh(checkLaserCmd);
+        } else {
+            checkLaserCmd = CmdConstant.CHECK_LASER_WIN
+                    .replace("@inPath", inPath)
+                    .replace("@outPath", outPath);
+            CmdUtils.callLine(checkLaserCmd);
+
+        }
+
+    }
+}

+ 157 - 0
src/main/java/com/fdkankan/scene/util/CmdUtils.java

@@ -0,0 +1,157 @@
+package com.fdkankan.scene.util;
+
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * Created by Xiewj on 2021/1/4 0004 14:53
+ */
+@Slf4j
+public class CmdUtils {
+
+
+    /**
+     * 调用算法 xx.sh 脚本
+     *
+     * @param command
+     */
+//    public static void callshell(String command){
+//        try {
+//            String[] cmd = new String[]{"/bin/sh", "-c", command};
+//            Process process = Runtime.getRuntime().exec(cmd);
+//            StreamGobbler errorGobbler = new StreamGobbler(process.getErrorStream(), "ERROR");
+//            errorGobbler.start();
+//            StreamGobbler outGobbler = new StreamGobbler(process.getInputStream(), "STDOUT");
+//            outGobbler.start();
+//            process.waitFor();
+//        } catch (Exception e) {
+//            e.printStackTrace();
+//        }
+//    }
+    static void callLineSh(String command) {
+        CmdUtils.callLineSh(command, null);
+
+    }
+
+    /**
+     * 直接java调用命令
+     *
+     * @param command
+     */
+    static void callLine(String command) {
+        CmdUtils.callLine(command, null);
+
+    }
+
+    /**
+     * 直接java调用命令
+     *
+     * @param command
+     */
+    static void callLineWin(String command) {
+        CmdUtils.callLineWin(command, null);
+
+    }
+
+    /**
+     * 直接java调用命令
+     *
+     * @param command
+     */
+    private static void callLineWin(String command, Integer lineSize) {
+        CmdUtils.log.info("cmd: " + command);
+        try {
+            String[] cmd = new String[]{"cmd ", "/c", command};
+            Process process = Runtime.getRuntime().exec(cmd);
+            CmdUtils.log.info("开始运行");
+            StreamGobblerLine errorGobbler = new StreamGobblerLine(process.getErrorStream(), "ERROR");
+            errorGobbler.start();
+            // 200行打印一次日志
+            StreamGobblerLine outGobbler = new StreamGobblerLine(process.getInputStream(), "STDOUT", lineSize);
+            outGobbler.start();
+            process.waitFor();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 直接java调用命令
+     *
+     * @param command
+     */
+    private static void callLine(String command, Integer lineSize) {
+        CmdUtils.log.info("cmd: " + command);
+        try {
+            Process process = Runtime.getRuntime().exec(command);
+            CmdUtils.log.info("开始运行");
+            StreamGobblerLine errorGobbler = new StreamGobblerLine(process.getErrorStream(), "ERROR");
+            errorGobbler.start();
+            // 200行打印一次日志
+            StreamGobblerLine outGobbler = new StreamGobblerLine(process.getInputStream(), "STDOUT", lineSize);
+            outGobbler.start();
+            process.waitFor();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * @param command  命令
+     * @param lineSize 日志输出行数 ,可以为null
+     */
+    private static void callLineSh(String command, Integer lineSize) {
+        CmdUtils.log.info("cmd: " + command);
+        try {
+            String[] cmd = new String[]{"/bin/sh", "-c", command};
+            Process process = Runtime.getRuntime().exec(cmd);
+            CmdUtils.log.info("开始运行");
+            StreamGobblerLine errorGobbler = new StreamGobblerLine(process.getErrorStream(), "ERROR");
+            errorGobbler.start();
+            // 200行打印一次日志
+            StreamGobblerLine outGobbler = new StreamGobblerLine(process.getInputStream(), "STDOUT", lineSize);
+            outGobbler.start();
+            process.waitFor();
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 调用sh脚本上传oss
+     */
+//    public static void ossUploadDir(String sceneCode, String uploadDir, String target){
+//
+//        String cmd = CmdConstant.OSSUTIL_UPLOAD_DIR;
+//        cmd = cmd.replaceAll("@sceneCode", sceneCode);
+//        cmd = cmd.replaceAll("@uploadDir", uploadDir);
+//        cmd = cmd.replaceAll("@target", target);
+//
+//        log.info("ossCmd: " + cmd);
+//        long start = System.currentTimeMillis();
+//        CmdUtils.callLineSh(cmd);
+//        long end = System.currentTimeMillis();
+//        log.info("场景码目录:{} 上传完成, 耗时:{} s" , sceneCode, (end-start)/1000 );
+//    }
+
+
+    /**
+     * 调用sh脚本上传oss
+     */
+    public static void ossUploadDir(String cmd) {
+
+//        log.info("ossCmd: " + cmd);
+        long start = System.currentTimeMillis();
+        CmdUtils.callLineSh(cmd);
+        long end = System.currentTimeMillis();
+        CmdUtils.log.info("场景码目录:{} 上传完成, 耗时:{} s", (end - start) / 1000);
+    }
+
+    public static void ossDeleteDir(String cmd) {
+        CmdUtils.log.info("ossCmd: " + cmd);
+        long start = System.currentTimeMillis();
+        CmdUtils.callLineSh(cmd);
+        long end = System.currentTimeMillis();
+        CmdUtils.log.info("删除目录完成, 耗时:{} s", (end - start) / 1000);
+
+    }
+}

+ 21 - 0
src/main/resources/application.yml

@@ -1,3 +1,24 @@
+# 项目相关配置
+fdkk:
+  # 文件路径 示例( Windows配置D:/fdkk/uploadPath,Linux配置 /home/fdkk/uploadPath)
+  profile: ${PROFILE_PATH}
+  # 获取ip地址开关
+  # 验证码类型 math 数组计算 char 字符验证
+  serverBasePath: D:\test
+  #算法工作目录
+  buildModelPath: ${BUILD_MODEL_PATH}
+  #算法软件目录
+  buildCallPath: ${BUILD_CALL_PATH}
+  binPath: ${BIN_PATH}
+  defaultFolder: datav1
+  # 是否本地化部署:开启此项会使用minio文件管理
+  isLocalization: true
+  # 是否使用文件存储系统
+  isBucket: false
+  # 开启定时任务统计
+  isActiveJobStatus: false
+  #是否使用软连接
+  isLink: false
 server:
   port: 8085
   servlet: