Преглед изворни кода

提交地磅计量初始化

chenxiaofei пре 4 месеци
родитељ
комит
2f4d9c418f
18 измењених фајлова са 2746 додато и 4 уклоњено
  1. 12 0
      iot-platform-common/pom.xml
  2. 73 0
      iot-platform-common/src/main/java/com/platform/constants/NumberConstant.java
  3. 51 0
      iot-platform-common/src/main/java/com/platform/constants/StringConstant.java
  4. 67 0
      iot-platform-common/src/main/java/com/platform/enums/AliyunOssFileTypeEnum.java
  5. 148 0
      iot-platform-common/src/main/java/com/platform/utils/Digests.java
  6. 154 0
      iot-platform-common/src/main/java/com/platform/utils/Encodes.java
  7. 82 0
      iot-platform-common/src/main/java/com/platform/utils/FileInfo.java
  8. 1421 0
      iot-platform-common/src/main/java/com/platform/utils/FileUtils.java
  9. 114 0
      iot-platform-common/src/main/java/com/platform/utils/IdWorker.java
  10. 381 0
      iot-platform-common/src/main/java/com/platform/utils/PasswordUtils.java
  11. 39 0
      iot-platform-manager/src/main/java/com/platform/api/controller/WeighbridgeController.java
  12. 58 0
      iot-platform-manager/src/main/java/com/platform/api/request/WeighbridgePushRequest.java
  13. 1 1
      iot-platform-manager/src/main/java/com/platform/entity/WeighbridgeRecord.java
  14. 124 0
      iot-platform-manager/src/main/java/com/platform/manage/WeighbridgeRecordManage.java
  15. 1 1
      iot-platform-manager/src/main/java/com/platform/mapper/WeighbridgeRecordMapper.java
  16. 1 1
      iot-platform-manager/src/main/java/com/platform/service/WeighbridgeRecordService.java
  17. 1 1
      iot-platform-manager/src/main/java/com/platform/service/impl/WeighbridgeRecordServiceImpl.java
  18. 18 0
      pom.xml

+ 12 - 0
iot-platform-common/pom.xml

@@ -36,6 +36,18 @@
             <groupId>org.apache.commons</groupId>
             <artifactId>commons-lang3</artifactId>
         </dependency>
+        <dependency>
+            <groupId>com.alibaba.cloud</groupId>
+            <artifactId>spring-cloud-starter-alicloud-oss</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-http</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-extra</artifactId>
+        </dependency>
     </dependencies>
     <build>
         <plugins>

+ 73 - 0
iot-platform-common/src/main/java/com/platform/constants/NumberConstant.java

@@ -0,0 +1,73 @@
+package com.platform.constants;
+
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+
+/**
+ * @description:    定义常量
+ * @author: LengFaQiang
+ * @copyright
+ * @create: 2022-01-27 16:02
+ **/
+public final class NumberConstant {
+    public static final int ZERO = 0;
+    public static final int ONE = 1;
+    public static final int TWO = 2;
+    public static final int THREE = 3;
+    public static final int FOUR = 4;
+    public static final int FIVE = 5;
+    public static final int SIX = 6;
+    public static final int SEVEN = 7;
+    public static final int EIGHT = 8;
+    public static final int NINE = 9;
+    public static final int TEN = 10;
+    public static final int ELEVEN = 11;
+    public static final int TWELVE = 12;
+    public static final int THREETEEN = 13;
+    public static final int FOURTEEN = 14;
+    public static final int ONE_FIVE = 15;
+    public static final int SIXTEEN = 16;
+    public static final int EIGHTTEEN = 18;
+    public static final int NINETEEN = 19;
+    public static final int TWETY = 20;
+    public static final int TWETYTHREE = 23;
+    public static final int TWENTY_FOUR = 24;
+    public static final int TWENTY_SIX = 26;
+    public static final int THIRTY = 30;
+    public static final int THIRTY_TREE = 32;
+    public static final int FOURTY = 40;
+    public static final int FIFTY = 50;
+    public static final int EIGTY = 80;
+    public static final int ONE_ZERO_ZERO = 100;
+    public static final int ONE_ONE_ZERO = 110;
+    public static final int ONE_ZERO_ONE = 101;
+    public static final int ONE_ONE_ONE = 111;
+    public static final int ONE_TWO_ONE = 121;
+    public static final int ONE_TWO_EIGHT = 128;
+    public static final int ONE_THREE_THREE = 133;
+    public static final int TWO_HUNDRED = 200;
+    public static final int TWO_FIVE_FIVE = 255;
+    public static final int TWO_FIVE_SIX = 256;
+    public static final int FOUR_HUNDRED = 400;
+    public static final int FOUR_ZERO_ONE = 401;
+    public static final int THREE_HUNDRED = 300;
+    public static final int THREE_FIVE_ZERO = 350;
+    public static final int FIVE_HUNDRED = 500;
+    public static final int EIGHT_HUNDRED = 800;
+    public static final int SIX_THREE_SEVEN_NINE = 6379;
+    public static final int ONE_ZERO_TWO_FOUR = 1024;
+    public static final int ONE_THOUSAND = 1000;
+    public static final int THREE_SIX_ZERO_ZERO = 3600;
+    public static final int FIFTY_MILLION = 52428800;
+    public static final double NINETY = 90.0D;
+    public static final double NEGATICE_NINETY = -90.0D;
+    public static final double ONE_HUNDRED_EIGHTY = 180.0D;
+    public static final double NEGATICE_ONE_HUNDRED_EIGHTY = -180.0D;
+    public static final int COOKIE_TIMEN = 300;
+
+    public static final BigDecimal ONE_HUNDRED = new BigDecimal("100.00");
+    public static final BigDecimal TEN_THOUSAND = new BigDecimal("10000.00");
+    public static final BigDecimal ZERO_TWO = BigDecimal.ZERO.setScale(NumberConstant.TWO, RoundingMode.DOWN);
+    public NumberConstant() {
+    }
+}

+ 51 - 0
iot-platform-common/src/main/java/com/platform/constants/StringConstant.java

@@ -0,0 +1,51 @@
+package com.platform.constants;
+
+import java.time.format.DateTimeFormatter;
+
+/**
+ * @description: 定义字符串常量
+ * @author: LengFaQiang
+ * @copyright
+ * @create: 2022-01-27 16:02
+ **/
+public final class StringConstant {
+    public static final String LEFT_SEPARATOR = "/";
+    public static final String LEFT_SEPARATORS = "//";
+    public static final String RIGHT_SEPARATOR = "\\";
+    public static final String COLON = ":";
+    public static final String SEMICOLON = ";";
+    public static final String POINT = ".";
+
+    public static final String COMMA = ",";
+
+    /**
+     * 中横线
+     */
+    public static final String HYPHEN = "-";
+
+    /**
+     * 下划线
+     */
+    public static final String UNDERLINE = "_";
+    public static final String HTTP_STRING = "http";
+    public static final String HTTPS_STRING = "https";
+    public static final String B = "B";
+    public static final String KB = "KB";
+
+    public static final String MB = "MB";
+    public static final String G = "G";
+    public static final String GB = "GB";
+    public static final String DEFAULT_DATE_PATTERN = "yyyy-MM-dd HH:mm:ss";
+    public static final String DEF_DATE_FORMAT = "yyyy-MM-dd";
+    public static final DateTimeFormatter YYYY_MM_DD_HH_MM_SS = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
+    public static final DateTimeFormatter YYYY_MM_DD = DateTimeFormatter.ofPattern("yyyy-MM-dd");
+    public static final DateTimeFormatter HH_MM_SS = DateTimeFormatter.ofPattern("HH:mm:ss");
+    public static final String DATE_YYYYMMDD = "yyyyMMdd";
+    public static final String ENCODING_UTF_EIGHT = "UTF-8";
+    public static final String ENCODING_UTF_SIXTEEN = "UTF-16";
+    public static final String ENCODING_GBK = "GBK";
+    public static final String ENCODING_ISO = "ISO8859-1";
+
+    public StringConstant() {
+    }
+}

+ 67 - 0
iot-platform-common/src/main/java/com/platform/enums/AliyunOssFileTypeEnum.java

@@ -0,0 +1,67 @@
+package com.platform.enums;
+
+/**
+ * @author lfdc
+ * @version 1.0
+ * @className AliyunOssFileTypeEnum
+ * @description 阿里云文件类型
+ * @company sckw
+ * @date 2023-06-05 13:06:54
+ */
+public enum AliyunOssFileTypeEnum {
+    BMP(".bmp","image/bmp"),
+    GIF(".gif","image/gif"),
+    JPEG(".jpeg","image/jpeg"),
+    JPG(".jpg","image/jpeg"),
+    PNG(".png","image/jpeg"),
+    HTML(".html","text/html"),
+    XML(".xml","text/xml"),
+    TXT(".txt","application/octet-stream"),
+    SQL(".sql","application/octet-stream"),
+    VSD(".vsd","application/vnd.visio"),
+    PDF(".pdf","application/pdf"),
+    PPT(".ppt","application/vnd.ms-powerpoint"),
+    PPTX(".pptx","application/vnd.ms-powerpoint"),
+    DOC(".doc","application/msword"),
+    DOCX(".docx","application/msword"),
+    XLS(".xls","application/vnd.ms-excel"),
+    XLSX(".xlsx","application/vnd.ms-excel"),
+    CSV(".csv","application/vnd.ms-excel");
+
+
+    String code;
+
+
+    String text;
+
+
+    AliyunOssFileTypeEnum() {
+    }
+
+
+    AliyunOssFileTypeEnum(String code, String text) {
+        this.code = code;
+        this.text = text;
+    }
+
+
+    public String getCode() {
+        return code;
+    }
+
+
+    public void setCode(String code) {
+        this.code = code;
+    }
+
+
+    public String getText() {
+        return text;
+    }
+
+
+    public void setText(String text) {
+        this.text = text;
+    }
+
+}

+ 148 - 0
iot-platform-common/src/main/java/com/platform/utils/Digests.java

@@ -0,0 +1,148 @@
+/**
+ * Copyright (c) 2005-2012 springside.org.cn
+ */
+package com.platform.utils;
+
+import org.apache.commons.lang3.Validate;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.security.GeneralSecurityException;
+import java.security.MessageDigest;
+import java.security.SecureRandom;
+
+/**
+ * 支持SHA-1/MD5消息摘要的工具类.
+ * 返回ByteSource,可进一步被编码为Hex, Base64或UrlSafeBase64
+ * @author calvin
+ */
+public class Digests {
+
+	private static final String SHA1 = "SHA-1";
+	private static final String MD5 = "MD5";
+
+	private static SecureRandom random = new SecureRandom();
+
+	/**
+	 * 对输入字符串进行md5散列.
+	 */
+	public static byte[] md5(byte[] input) {
+		return digest(input, MD5, null, 1);
+	}
+	public static byte[] md5(byte[] input, int iterations) {
+		return digest(input, MD5, null, iterations);
+	}
+	
+	/**
+	 * 对输入字符串进行sha1散列.
+	 */
+	public static byte[] sha1(byte[] input) {
+		return digest(input, SHA1, null, 1);
+	}
+
+	public static byte[] sha1(byte[] input, byte[] salt) {
+		return digest(input, SHA1, salt, 1);
+	}
+
+	public static byte[] sha1(byte[] input, byte[] salt, int iterations) {
+		return digest(input, SHA1, salt, iterations);
+	}
+
+	/**
+	 * 对字符串进行散列, 支持md5与sha1算法.
+	 */
+	private static byte[] digest(byte[] input, String algorithm, byte[] salt, int iterations) {
+		try {
+			MessageDigest digest = MessageDigest.getInstance(algorithm);
+
+			if (salt != null) {
+				digest.update(salt);
+			}
+
+			byte[] result = digest.digest(input);
+
+			for (int i = 1; i < iterations; i++) {
+				digest.reset();
+				result = digest.digest(result);
+			}
+			return result;
+		} catch (GeneralSecurityException e) {
+            e.printStackTrace();
+            return null;
+		}
+	}
+
+	/**
+	 * 生成随机的Byte[]作为salt.
+	 * 
+	 * @param numBytes byte数组的大小
+	 */
+	public static byte[] generateSalt(int numBytes) {
+		Validate.isTrue(numBytes > 0, "numBytes argument must be a positive integer (1 or larger)", numBytes);
+
+		byte[] bytes = new byte[numBytes];
+		random.nextBytes(bytes);
+		return bytes;
+	}
+
+	/**
+	 * 对文件进行md5散列.
+	 */
+	public static byte[] md5(InputStream input) throws IOException {
+		return digest(input, MD5);
+	}
+
+	/**
+	 * 对文件进行sha1散列.
+	 */
+	public static byte[] sha1(InputStream input) throws IOException {
+		return digest(input, SHA1);
+	}
+
+	private static byte[] digest(InputStream input, String algorithm) throws IOException {
+		try {
+			MessageDigest messageDigest = MessageDigest.getInstance(algorithm);
+			int bufferLength = 8 * 1024;
+			byte[] buffer = new byte[bufferLength];
+			int read = input.read(buffer, 0, bufferLength);
+
+			while (read > -1) {
+				messageDigest.update(buffer, 0, read);
+				read = input.read(buffer, 0, bufferLength);
+			}
+
+			return messageDigest.digest();
+		} catch (GeneralSecurityException e) {
+            e.printStackTrace();
+            return null;
+		}
+	}
+	
+	public static String string2MD5(String inStr){  
+        MessageDigest md5 = null;  
+        try{  
+            md5 = MessageDigest.getInstance("MD5");  
+        }catch (Exception e){  
+            System.out.println(e.toString());  
+            e.printStackTrace();  
+            return "";  
+        }  
+        char[] charArray = inStr.toCharArray();  
+        byte[] byteArray = new byte[charArray.length];  
+  
+        for (int i = 0; i < charArray.length; i++) {
+            byteArray[i] = (byte) charArray[i];
+        }
+        byte[] md5Bytes = md5.digest(byteArray);  
+        StringBuffer hexValue = new StringBuffer();  
+        for (int i = 0; i < md5Bytes.length; i++){  
+            int val = ((int) md5Bytes[i]) & 0xff;  
+            if (val < 16) {
+                hexValue.append("0");
+            }
+            hexValue.append(Integer.toHexString(val));  
+        }  
+        return hexValue.toString();  
+  
+    }  
+}

+ 154 - 0
iot-platform-common/src/main/java/com/platform/utils/Encodes.java

@@ -0,0 +1,154 @@
+/**
+ * Copyright (c) 2005-2012 springside.org.cn
+ */
+package com.platform.utils;
+
+import org.apache.commons.codec.DecoderException;
+import org.apache.commons.codec.binary.Base64;
+import org.apache.commons.codec.binary.Hex;
+import org.apache.commons.lang3.StringEscapeUtils;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+import java.net.URLEncoder;
+
+/**
+ * 封装各种格式的编码解码工具类.
+ * 1.Commons-Codec的 hex/base64 编码
+ * 2.自制的base62 编码
+ * 3.Commons-Lang的xml/html escape
+ * 4.JDK提供的URLEncoder
+ * @author calvin
+ * @version 2013-01-15
+ */
+public class Encodes {
+
+	private static final String DEFAULT_URL_ENCODING = "UTF-8";
+	private static final char[] BASE62 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz".toCharArray();
+
+	/**
+	 * Hex编码.
+	 */
+	public static String encodeHex(byte[] input) {
+		return new String(Hex.encodeHex(input));
+	}
+
+	/**
+	 * Hex解码.
+	 */
+	public static byte[] decodeHex(String input) {
+		try {
+			return Hex.decodeHex(input.toCharArray());
+		} catch (DecoderException e) {
+			e.printStackTrace();
+		}
+		return null;
+	}
+
+	/**
+	 * Base64编码.
+	 */
+	public static String encodeBase64(byte[] input) {
+		return new String(Base64.encodeBase64(input));
+	}
+	
+	/**
+	 * Base64编码.
+	 */
+	public static String encodeBase64(String input) {
+		try {
+			return new String(Base64.encodeBase64(input.getBytes(DEFAULT_URL_ENCODING)));
+		} catch (UnsupportedEncodingException e) {
+			return "";
+		}
+	}
+
+//	/**
+//	 * Base64编码, URL安全(将Base64中的URL非法字符'+'和'/'转为'-'和'_', 见RFC3548).
+//	 */
+//	public static String encodeUrlSafeBase64(byte[] input) {
+//		return Base64.encodeBase64URLSafe(input);
+//	}
+
+	/**
+	 * Base64解码.
+	 */
+	public static byte[] decodeBase64(String input) {
+		return Base64.decodeBase64(input.getBytes());
+	}
+	
+	/**
+	 * Base64解码.
+	 */
+	public static String decodeBase64String(String input) {
+		try {
+			return new String(Base64.decodeBase64(input.getBytes()), DEFAULT_URL_ENCODING);
+		} catch (UnsupportedEncodingException e) {
+			return "";
+		}
+	}
+
+	/**
+	 * Base62编码。
+	 */
+	public static String encodeBase62(byte[] input) {
+		char[] chars = new char[input.length];
+		for (int i = 0; i < input.length; i++) {
+			chars[i] = BASE62[((input[i] & 0xFF) % BASE62.length)];
+		}
+		return new String(chars);
+	}
+
+	/**
+	 * Html 转码.
+	 */
+	public static String escapeHtml(String html) {
+		return StringEscapeUtils.escapeHtml4(html);
+	}
+
+	/**
+	 * Html 解码.
+	 */
+	public static String unescapeHtml(String htmlEscaped) {
+		return StringEscapeUtils.unescapeHtml4(htmlEscaped);
+	}
+
+	/**
+	 * Xml 转码.
+	 */
+	public static String escapeXml(String xml) {
+		return StringEscapeUtils.escapeXml10(xml);
+	}
+
+	/**
+	 * Xml 解码.
+	 */
+	public static String unescapeXml(String xmlEscaped) {
+		return StringEscapeUtils.unescapeXml(xmlEscaped);
+	}
+
+	/**
+	 * URL 编码, Encode默认为UTF-8. 
+	 */
+	public static String urlEncode(String part) {
+		try {
+			return URLEncoder.encode(part, DEFAULT_URL_ENCODING);
+		} catch (UnsupportedEncodingException e) {
+			e.printStackTrace();
+		}
+		return null;
+	}
+
+	/**
+	 * URL 解码, Encode默认为UTF-8. 
+	 */
+	public static String urlDecode(String part) {
+
+		try {
+			return URLDecoder.decode(part, DEFAULT_URL_ENCODING);
+		} catch (UnsupportedEncodingException e) {
+			e.printStackTrace();
+		}
+		return null;
+	}
+}

+ 82 - 0
iot-platform-common/src/main/java/com/platform/utils/FileInfo.java

@@ -0,0 +1,82 @@
+package com.platform.utils;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * @author lfdc
+ * @description 文件信息
+ * @date 2023-07-03 15:07:00
+ */
+@Data
+public class FileInfo implements Serializable {
+
+    /**
+     * 文件上传类型 oss/qiniuyun
+     */
+    @NotBlank(message = "文件上传类型不能为空")
+    private String type;
+
+    /**
+     * 文件原名称
+     */
+    @NotBlank(message = "文件原名称不能为空")
+    private String fileOriginalName;
+    /**
+     * 文件加密key
+     */
+    @NotBlank(message = "文件加密key不能为空")
+    private String fileMd5;
+
+    /**
+     * 文件新名称
+     */
+    @NotBlank(message = "文件新名称不能为空")
+    private String fileName;
+    /**
+     * 文件后缀
+     */
+    @NotBlank(message = "文件后缀不能为空")
+    private String fileSuffix;
+    /**
+     * 文件大小  默认为mb
+     */
+    @NotNull(message = "文件大小不能为空")
+    private BigDecimal fileSize;
+
+    /**
+     * 文件相对路径
+     */
+    @NotBlank(message = "文件相对路径不能为空")
+    private String filePath;
+    /**
+     * 文件绝对路径
+     */
+    @NotBlank(message = "文件绝对路径不能为空")
+    private String fileAbsolutePath;
+
+    @JsonFormat(timezone = "yyyy-MM-dd HH:mm:ss")
+    @NotBlank
+    private String createTime;
+
+    @NotNull(message = "文件修改人不能为空")
+    private Long updateBy;
+    @NotNull(message = "文件上传人不能为空")
+    private Long createBy;
+
+    @NotBlank
+    @JsonFormat(timezone = "yyyy-MM-dd HH:mm:ss")
+    private String updateTime;
+
+    @NotNull(message = "文件删除标志不能为空")
+    private Integer delFlag;
+
+    @NotNull(message = "文件状态不能为空")
+    private Integer status;
+
+}

+ 1421 - 0
iot-platform-common/src/main/java/com/platform/utils/FileUtils.java

@@ -0,0 +1,1421 @@
+package com.platform.utils;
+
+
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.util.StrUtil;
+import com.aliyun.oss.*;
+import com.aliyun.oss.model.*;
+
+import com.platform.constants.NumberConstant;
+import com.platform.constants.StringConstant;
+import com.platform.enums.AliyunOssFileTypeEnum;
+import jakarta.annotation.PostConstruct;
+import jakarta.servlet.http.HttpServletResponse;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.stereotype.Component;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.imageio.ImageIO;
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.io.*;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.net.URL;
+import java.net.URLEncoder;
+import java.text.DecimalFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author lfdc
+ * @version 1.0
+ * @className FileUtils
+ * @description Oss文件工具类
+ * @company sckw
+ * @date 2023-06-05 09:06:57
+ */
+@Slf4j
+@Component
+@Configuration
+public class FileUtils {
+
+    private static String BASE_DIR = "kll/uploads/";
+
+    //oss客户端连接
+    private static OSS ossclient = null;
+
+
+    private static String DEFAULT_ENDPOINT = "oss-cn-chengdu.aliyuncs.com";
+    private static String DEFAULT_ACCESS_KEY_ID = "LTAI5tHq44Cn3p8qqPN7DKc1";
+    private static String DEFAULT_ACCESS_KEY_SECRET = "nQaRrRwlcIWD5jNBu9CZ14YZhaRbTG";
+    private static String DEFAULT_BUCKET_NAME = "saas-four";
+
+    private static String endpoint;
+    private static String accessKeyId;
+    private static String accessKeySecret;
+    private static String bucketName;
+    private static FileUtils fileUtils;
+
+    @Value("${aliyun.oss.endpoint}")
+    private String oss_endpoint;
+
+    @Value("${aliyun.oss.accessKeyId}")
+    private String oss_accessKeyId;
+
+    @Value("${aliyun.oss.secret}")
+    private String oss_accessKeySecret;
+
+    @Value("${aliyun.oss.bucket}")
+    public String oss_bucketName;
+
+    private static void defaultOss() {
+        if (StringUtils.isBlank(endpoint)) {
+            endpoint = DEFAULT_ENDPOINT;
+        }
+        if (StringUtils.isBlank(accessKeyId)) {
+            accessKeyId = DEFAULT_ACCESS_KEY_ID;
+        }
+        if (StringUtils.isBlank(accessKeySecret)) {
+            accessKeySecret = DEFAULT_ACCESS_KEY_SECRET;
+        }
+        if (StringUtils.isBlank(bucketName)) {
+            bucketName = DEFAULT_BUCKET_NAME;
+        }
+    }
+
+    @PostConstruct
+    public void init() {
+        endpoint = this.oss_endpoint;
+        accessKeyId = this.oss_accessKeyId;
+        accessKeySecret = this.oss_accessKeySecret;
+        bucketName = this.oss_bucketName;
+    }
+
+
+    public static FileInfo getFileDataList(MultipartFile file) {
+        FileInfo fileInfo = new FileInfo();
+        String oFileName = file.getOriginalFilename();
+        BigDecimal fileSize = FileUtils.getFileSize(file, StringConstant.KB);
+        fileInfo.setFileSize(fileSize);
+        fileInfo.setFileOriginalName(oFileName);
+        fileInfo.setFileSuffix(FilenameUtils.getExtension(oFileName));
+        return fileInfo;
+    }
+
+
+    /**
+     * 获取oss 地址前缀
+     *
+     * @return
+     */
+    public static String getOSSAddressPrefix() {
+        defaultOss();
+        return StringConstant.HTTPS_STRING
+                + StringConstant.COLON
+                + StringConstant.LEFT_SEPARATORS
+                + bucketName
+                + StringConstant.POINT
+                + endpoint
+                + StringConstant.LEFT_SEPARATOR;
+    }
+
+    /**
+     * 分割上传地址 目前仅用于oss
+     *
+     * @param replace 上传的绝对路径
+     * @return 分割后的相对路径
+     */
+    public static String replaceAll(String replace) {
+        if (StringUtils.isBlank(replace)) {
+            return null;
+        }
+        return replace.replaceAll(getOSSAddressPrefix(), "");
+    }
+
+    /**
+     * 拼接上传地址 目前仅用于oss
+     *
+     * @param replace 相对路径url
+     * @return 绝对路径url
+     */
+    public static String splice(String replace) {
+        StringBuilder stringBuilder = new StringBuilder();
+        if (StringUtils.isBlank(replace)) {
+            return null;
+        }
+        if (StrUtil.startWith(replace, "http")) {
+            return replace;
+        }
+        return stringBuilder.append(getOSSAddressPrefix()).append(replace).toString();
+    }
+
+
+    /**
+     * 分割上传地址 目前仅用于oss
+     *
+     * @param replace 上传的绝对路径
+     * @return 分割后的相对路径
+     */
+    public static String replaceAllBatch(String replace) {
+        StringBuilder stringBuilder = new StringBuilder();
+        if (StringUtils.isBlank(replace)) {
+            return null;
+        }
+        String[] split = replace.split(",");
+        if (split.length > 0) {
+            for (int i = 0; i < split.length; i++) {
+                if (i != (split.length - 1)) {
+                    stringBuilder.append(split[i].replaceAll(getOSSAddressPrefix(), "")).append(",");
+                } else {
+                    stringBuilder.append(split[i].replaceAll(getOSSAddressPrefix(), ""));
+                }
+
+            }
+            return stringBuilder.toString();
+        }
+        return null;
+    }
+
+    /**
+     * 拼接上传地址 目前仅用于oss
+     *
+     * @param replace 相对路径url
+     * @return 绝对路径url
+     */
+    public static String spliceBatch(String replace) {
+        StringBuilder stringBuilder = new StringBuilder();
+        if (StringUtils.isBlank(replace)) {
+            return null;
+        }
+        String[] split = replace.split(",");
+        if (split.length > 0) {
+            for (int i = 0; i < split.length; i++) {
+                if (i != (split.length - 1)) {
+                    stringBuilder.append(getOSSAddressPrefix()).append(split[i]).append(",");
+                } else {
+                    stringBuilder.append(getOSSAddressPrefix()).append(split[i]);
+                }
+            }
+            return stringBuilder.toString();
+        }
+        return null;
+    }
+
+
+    /**
+     * 获取指定文件或文件夹的后缀名
+     *
+     * @param fileName 文件名称
+     * @return
+     */
+    public static String getFileSuffix(String fileName) {
+        //例如:abc.png  截取后:.png
+        return fileName.substring(fileName.lastIndexOf("."));
+    }
+
+
+    /**
+     * 文件上传
+     *
+     * @param file     文件
+     * @return
+     */
+    public static Map<String, String> uploadFileByInfo(MultipartFile file) {
+        Map<String, String> infoMap = new HashMap<>(NumberConstant.SIXTEEN);
+        //创建OSSClient实例
+        defaultOss();
+        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
+        try {
+            //容器不存在,就创建
+            if (!ossClient.doesBucketExist(bucketName)) {
+                ossClient.createBucket(bucketName);
+                CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName);
+                createBucketRequest.setCannedACL(CannedAccessControlList.PublicRead);
+                ossClient.createBucket(createBucketRequest);
+            }
+            //上传文件流
+            InputStream inputStream = file.getInputStream();
+            String fileName = FilenameUtils.getBaseName(file.getOriginalFilename());
+            //生成随机唯一值,使用uuid,添加到文件名称里面 改成使用加密
+//            fileName = PasswordUtils.md5(fileName);
+            fileName = PasswordUtils.md5(fileName);
+            String fileSuffix = FileUtils.getFileSuffix(file.getOriginalFilename());
+            //不带后缀
+            infoMap.put("fileMd5", fileName);
+            infoMap.put("fileName", fileName + fileSuffix);
+            //按照当前日期,创建文件夹,上传到创建文件夹里面
+            String timeUrl = new DateTime().toString("yyyyMMdd");
+            fileName = timeUrl + "/" + fileName;
+            String filePath = BASE_DIR + fileName + fileSuffix;
+            //调用方法实现上传
+            ossClient.putObject(bucketName, filePath, inputStream);
+            //获取上传后的文件地址
+            //String url1 = getUrl(ossClient, bucketName, filePath);
+            //关闭OSSClient。
+            ossClient.shutdown();
+            //上传之后文件路径
+            //String url = "https://" + bucketName + "." + endpoint + "/" + filePath;
+            //绝对路径 "https://kaiwu-saas.oss-cn-chengdu.aliyuncs.com/+ filePath;"
+            StringBuilder stringBuilder = new StringBuilder();
+            stringBuilder.append(StringConstant.HTTPS_STRING)
+                    .append(StringConstant.COLON)
+                    .append(StringConstant.LEFT_SEPARATORS)
+                    .append(bucketName)
+                    .append(StringConstant.POINT)
+                    .append(endpoint)
+                    .append(StringConstant.LEFT_SEPARATOR);
+//            String url = stringBuilder.append(filePath).toString();
+            //相对路径
+            String url = filePath;
+            //返回 上传文件地址
+            infoMap.put("filePath", url);
+        } catch (IOException e) {
+            infoMap.put("filePath", null);
+            //关闭OSSClient。
+            ossClient.shutdown();
+            e.printStackTrace();
+            log.error("oss-upload-file-error:{}", e.getMessage(), e);
+            throw new RuntimeException("oss-upload-file-error:" + e.getMessage());
+        }
+        return infoMap;
+    }
+
+    /**
+     * 上传文件
+     * <p>
+     * kll/uploads/年月日/md5(file).xxx
+     *
+     * @param file
+     * @return
+     */
+    public static String uploadFile(MultipartFile file) {
+        // 私有云要关闭CNAME
+        ClientBuilderConfiguration conf = new ClientBuilderConfiguration();
+        conf.setSupportCname(false);
+        try {
+            //创建OSSClient实例
+            defaultOss();
+            OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
+
+            //容器不存在,就创建
+            if (!ossClient.doesBucketExist(bucketName)) {
+                ossClient.createBucket(bucketName);
+                CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName);
+                createBucketRequest.setCannedACL(CannedAccessControlList.PublicRead);
+                ossClient.createBucket(createBucketRequest);
+            }
+            //上传文件流
+            InputStream inputStream = file.getInputStream();
+            String fileName = file.getOriginalFilename();
+            //生成随机唯一值,使用uuid,添加到文件名称里面
+            long uuid = new IdWorker(1).nextId();
+//            fileName = String.valueOf(uuid) + fileName;
+            fileName = PasswordUtils.md5(fileName);
+            //按照当前日期,创建文件夹,上传到创建文件夹里面
+            //2021/02/02/01.jpgossClient = {OSSClient@13049}
+            String timeUrl = new DateTime().toString("yyyyMMdd");
+            fileName = timeUrl + "/" + fileName;
+            String filePath = BASE_DIR + fileName;
+            /**设置上传内容类型*/
+            ObjectMetadata objectMeta = new ObjectMetadata();
+            objectMeta.setContentType(FileUtils.getContentTypeByOSS(file.getOriginalFilename()));
+            //调用方法实现上传
+            ossClient.putObject(bucketName, filePath, inputStream, objectMeta);
+            //上传后的文件地址
+//            String url1 = getUrl(ossClient, bucketName, filePath);
+//            System.out.println(url1);
+            //关闭OSSClient。
+            ossClient.shutdown();
+            //上传之后文件路径
+            //https://yygh-atguigu.oss-cn-beijing.aliyuncs.com/01.jpg
+            String url = "https://" + bucketName + "." + endpoint + "/" + filePath;
+            //返回 上传文件地址
+            return url;
+        } catch (IOException e) {
+            e.printStackTrace();
+            log.error("oss-upload-file-error:{}", e.getMessage(), e);
+            return null;
+        }
+    }
+
+    /**
+     * 文件上传
+     *
+     * @param inputStream      文件流
+     * @param originalFilename 文件原名称
+     * @return
+     */
+    public static Map<String, String> uploadFileByInfo(InputStream inputStream, String originalFilename) {
+        Map<String, String> infoMap = new HashMap<>(NumberConstant.SIXTEEN);
+        //创建OSSClient实例
+        defaultOss();
+        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
+        try {
+            //容器不存在,就创建
+            if (!ossClient.doesBucketExist(bucketName)) {
+                ossClient.createBucket(bucketName);
+                CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName);
+                createBucketRequest.setCannedACL(CannedAccessControlList.PublicRead);
+                ossClient.createBucket(createBucketRequest);
+            }
+            //上传文件流
+            String fileName = FilenameUtils.getBaseName(originalFilename);
+            //生成随机唯一值,使用uuid,添加到文件名称里面 改成使用加密
+//            fileName = PasswordUtils.md5(fileName);
+            fileName = PasswordUtils.md5(fileName);
+            String fileSuffix = FileUtils.getFileSuffix(originalFilename);
+            //不带后缀
+            infoMap.put("fileMd5", fileName);
+            infoMap.put("fileName", fileName + fileSuffix);
+            //按照当前日期,创建文件夹,上传到创建文件夹里面
+            //2021/02/02/01.jpg
+            String timeUrl = new DateTime().toString("yyyyMMdd");
+            fileName = timeUrl + "/" + fileName;
+            String filePath = BASE_DIR + fileName + fileSuffix;
+            //调用方法实现上传
+            ossClient.putObject(bucketName, filePath, inputStream);
+            //上传后的文件地址
+//            String url1 = getUrl(ossClient, bucketName, filePath);
+            //关闭OSSClient。
+            ossClient.shutdown();
+            //上传之后文件路径
+//            String url = "https://" + bucketName + "." + endpoint + "/" + filePath;
+            //绝对路径 "https://kaiwu-saas.oss-cn-chengdu.aliyuncs.com/+ filePath;"
+//            String url = StringConstant.HTTPS_STRING+StringConstant.COLON+StringConstant.LEFT_SEPARATORS + bucketName + StringConstant.POINT + endpoint + StringConstant.LEFT_SEPARATOR+ filePath;
+            //相对路径
+            String url = filePath;
+            //返回 上传文件地址
+            infoMap.put("filePath", url);
+        } catch (Exception e) {
+            infoMap.put("filePath", null);
+            //关闭OSSClient。
+            ossClient.shutdown();
+            e.printStackTrace();
+            log.error("oss-upload-file-error:{}", e.getMessage(), e);
+            throw new RuntimeException("oss-upload-file-error:" + e.getMessage());
+        }
+        return infoMap;
+    }
+
+
+    /**
+     * 文件上传
+     *
+     * @param file     文件流
+     * @param fileInfo 文件对象文件枚举-暂时不使用
+     * @return
+     */
+    public static FileInfo uploadFileInfo(MultipartFile file, FileInfo fileInfo) {
+        //创建OSSClient实例
+        defaultOss();
+        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
+        try {
+            //容器不存在,就创建
+            if (!ossClient.doesBucketExist(bucketName)) {
+                ossClient.createBucket(bucketName);
+                CreateBucketRequest createBucketRequest = new CreateBucketRequest(bucketName);
+                createBucketRequest.setCannedACL(CannedAccessControlList.PublicRead);
+                ossClient.createBucket(createBucketRequest);
+            }
+            //上传文件流
+            InputStream inputStream = file.getInputStream();
+            String fileName = FilenameUtils.getBaseName(file.getOriginalFilename());
+            //生成随机唯一值,使用uuid,添加到文件名称里面 改成使用加密
+            //fileName = PasswordUtils.md5(fileName);
+            fileName = PasswordUtils.md5(fileName) + System.currentTimeMillis();
+            String fileSuffix = FileUtils.getFileSuffix(file.getOriginalFilename());
+            //不带后缀
+            fileInfo.setFileMd5(fileName);
+            fileInfo.setFileName(fileName + fileSuffix);
+            //按照当前日期,创建文件夹,上传到创建文件夹里面
+            String timeUrl = new DateTime().toString(StringConstant.DATE_YYYYMMDD);
+            fileName = timeUrl + StringConstant.LEFT_SEPARATOR + fileName;
+            String filePath = BASE_DIR + fileName + fileSuffix;
+            //调用方法实现上传
+            ossClient.putObject(bucketName, filePath, inputStream);
+            //获取上传后的文件地址
+            //String url1 = getUrl(ossClient, bucketName, filePath);
+            //关闭OSSClient。
+            ossClient.shutdown();
+            //上传之后文件路径
+            //String url = "https://" + bucketName + "." + endpoint + "/" + filePath;
+            //绝对路径 "https://kaiwu-saas.oss-cn-chengdu.aliyuncs.com/+ filePath;"
+            StringBuilder stringBuilder = new StringBuilder();
+            stringBuilder.append(StringConstant.HTTPS_STRING)
+                    .append(StringConstant.COLON)
+                    .append(StringConstant.LEFT_SEPARATORS)
+                    .append(bucketName)
+                    .append(StringConstant.POINT)
+                    .append(endpoint)
+                    .append(StringConstant.LEFT_SEPARATOR);
+            String fileAbsolutePath = stringBuilder.append(filePath).toString();
+            fileInfo.setFileAbsolutePath(fileAbsolutePath);
+            //相对路径
+            String url = filePath;
+            //返回 上传文件地址
+            fileInfo.setFilePath(url);
+        } catch (IOException e) {
+            fileInfo.setFilePath(null);
+            //关闭OSSClient。
+            ossClient.shutdown();
+            e.printStackTrace();
+            log.error("oss-upload-file-error:{}", e.getMessage(), e);
+            throw new RuntimeException("oss-upload-file-error:" + e.getMessage());
+        }
+        return fileInfo;
+    }
+
+
+    /**
+     * 获取文件上传大小
+     *
+     * @param file
+     * @return
+     */
+    public static String getFileSize(MultipartFile file) {
+        long size = file.getSize();
+        DecimalFormat df = new DecimalFormat("#.00");
+        String fileSizeString;
+        if (size < 1024) {
+            fileSizeString = df.format((double) size) + "B";
+        } else if (size < 1048576) {
+            fileSizeString = df.format((double) size / 1024) + "KB";
+        } else if (size < 1073741824) {
+            fileSizeString = df.format((double) size / 1048576) + "MB";
+        } else {
+            fileSizeString = df.format((double) size / 1073741824) + "GB";
+        }
+        return fileSizeString;
+    }
+
+    /**
+     * 获取文件上传大小
+     *
+     * @param file 当前默认使用 kb
+     * @return
+     */
+    public static BigDecimal getFileSize(MultipartFile file, String type) {
+        long size = file.getSize();
+        BigDecimal bigDecimal = new BigDecimal(NumberConstant.ZERO);
+        if (StringUtils.isBlank(type)) {
+            type = StringConstant.KB;
+        }
+        switch (type) {
+            case "B":
+                bigDecimal = new BigDecimal((double) size);
+                break;
+            case "KB":
+                bigDecimal = new BigDecimal((double) size / 1024);
+                break;
+            case "MB":
+                bigDecimal = new BigDecimal((double) size / 1048576);
+                break;
+            case "GB":
+                bigDecimal = new BigDecimal((double) size / 1073741824);
+                break;
+            default:
+                throw new RuntimeException("file size error");
+        }
+        return bigDecimal.setScale(6, RoundingMode.HALF_UP);
+    }
+
+    /**
+     * 获得阿里云OSS客户端对象
+     *
+     * @param ossEndpoint
+     * @param accessId
+     * @param accessKey
+     * @return
+     */
+    public static OSS getOssClient(String ossEndpoint, String accessId, String accessKey) {
+        if (ossclient == null) {
+            ossclient = new OSSClientBuilder().build(ossEndpoint, accessId, accessKey);
+        }
+        return ossclient;
+    }
+
+    /**
+     * 通过文件名判断并获取OSS服务文件上传时文件的contentType
+     *
+     * @param fileName 文件名
+     * @return 文件的contentType
+     */
+    public static String getContentType(String fileName) {
+        // 文件的后缀名
+        String fileExtension = fileName.substring(fileName.lastIndexOf("."));
+        log.info("getContentType->fileName={},fileExtension={}", fileName, fileExtension);
+        for (AliyunOssFileTypeEnum e : AliyunOssFileTypeEnum.values()) {
+            if (e.getCode().equalsIgnoreCase(fileExtension)) {
+                return e.getText();
+            }
+        }
+        // 默认返回类型
+        return AliyunOssFileTypeEnum.TXT.getText();
+    }
+
+    /**
+     * @param fileName
+     * @param response
+     */
+    public static void downOSSFile(String fileName, HttpServletResponse response) {
+        BufferedInputStream input = null;
+        OutputStream outputStream = null;
+        defaultOss();
+        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
+//        OSSObject ossObject = ossClient.getObject(bucketName, folder + fileName);
+        OSSObject ossObject = ossClient.getObject(bucketName, fileName);
+        try {
+            response.reset();
+            response.setCharacterEncoding("utf-8");
+            response.setContentType("application/x-msdownload");
+            response.addHeader("Content-Disposition",
+                    "attachment;filename=" + new String(fileName.getBytes("gb2312"), "ISO8859-1"));
+
+            input = new BufferedInputStream(ossObject.getObjectContent());
+            byte[] buffBytes = new byte[1024];
+            outputStream = response.getOutputStream();
+            int read = 0;
+            while ((read = input.read(buffBytes)) != -1) {
+                outputStream.write(buffBytes, 0, read);
+            }
+            outputStream.flush();
+            // 数据读取完成后,获取的流必须关闭,否则会造成连接泄漏,导致请求无连接可用,程序无法正常工作。
+            ossObject.close();
+        } catch (IOException ex) {
+            ex.printStackTrace();
+        } finally {
+            try {
+                if (outputStream != null) {
+                    outputStream.close();
+                }
+                if (input != null) {
+                    input.close();
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+        }
+        ossClient.shutdown();
+    }
+
+
+    /**
+     * 通过文件名字下载
+     *
+     * @param response response
+     * @param fileName 文件名字,带后缀,例子:postman.txt
+     *                 文件全路径 kll/uploads/20230605/146325493677821952598454132.txt 去除“https://kaiwu-saas.oss-cn-chengdu.aliyuncs.com/”
+     */
+    public static void downloadByFileName(HttpServletResponse response, String fileName) {
+        defaultOss();
+        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
+        OSSObject ossObject = ossClient.getObject(bucketName, fileName);
+        boolean exist = ossClient.doesObjectExist(bucketName, fileName);
+        if (!exist) {
+            throw new RuntimeException("下载文件不存在!");
+        }
+        String contentType = ossObject.getObjectMetadata().getContentType();
+        String contentType1 = getContentType(fileName);
+//        System.out.println("contentType:" + contentType);
+//        System.out.println("contentType1:" + contentType1);
+        //设置响应内容类型,当设置了ContentType为“image/jpg”时,浏览器可以直接显示图片;
+//        response.setContentType(contentType);
+        BufferedInputStream in = new BufferedInputStream(ossObject.getObjectContent());
+        try {
+            BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
+            //通知浏览器以附件形式下载
+//            fileName = URLEncoder.encode(fileName, "UTF-8").replaceAll("\\+", "%20");
+            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "utf-8").replaceAll("\\+", "%20"));
+            byte[] car = new byte[1024];
+            int len = 0;
+            while ((len = in.read(car)) != -1) {
+                out.write(car, 0, len);
+            }
+            out.flush();
+            out.close();
+            in.close();
+            ossClient.shutdown();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 创建存储空间
+     *
+     * @param ossClient  OSS连接
+     * @param bucketName 存储空间
+     * @return
+     */
+    public static String createBucketName(OSS ossClient, String bucketName) {
+        // 存储空间
+        final String bucketNames = bucketName;
+        if (!ossClient.doesBucketExist(bucketName)) {
+            // 创建存储空间
+            Bucket bucket = ossClient.createBucket(bucketName);
+            log.info("创建存储空间成功");
+            return bucket.getName();
+        }
+        return bucketNames;
+    }
+
+
+    /**
+     * 删除存储空间bucketName
+     *
+     * @param ossClient  oss对象
+     * @param bucketName 存储空间
+     */
+    public static void deleteBucket(OSS ossClient, String bucketName) {
+        ossClient.deleteBucket(bucketName);
+        log.info("删除" + bucketName + "Bucket成功");
+    }
+
+
+    /**
+     * 创建模拟文件夹:多级目录
+     *
+     * @param ossClient  oss连接
+     * @param bucketName 存储空间
+     * @param folder     模拟文件夹名如"upload/2023/01/11/"
+     * @return 文件夹名
+     */
+    public static String createFolder(OSS ossClient, String bucketName, String folder) {
+        // 文件夹名
+        final String keySuffixWithSlash = folder;
+        // 判断文件夹是否存在,不存在则创建
+        if (!ossClient.doesObjectExist(bucketName, keySuffixWithSlash)) {
+            // 创建文件夹
+            ossClient.putObject(bucketName, keySuffixWithSlash, new ByteArrayInputStream(new byte[0]));
+            log.info("创建文件夹成功");
+            // 得到文件夹名
+            OSSObject object = ossClient.getObject(bucketName, keySuffixWithSlash);
+            String fileDir = object.getKey();
+            return fileDir;
+        }
+        return keySuffixWithSlash;
+    }
+
+
+    /**
+     * 根据key删除OSS服务器上的文件
+     *
+     * @param ossClient  oss连接
+     * @param bucketName 存储空间
+     * @param key        Bucket下的文件的路径名+文件名 如:"upload/2023/01/11/cake.jpg"
+     */
+    public static void deleteObject(OSS ossClient, String bucketName, String key) {
+        ossClient.deleteObject(bucketName, key);
+        log.info("删除" + bucketName + "下的文件" + key + "成功");
+    }
+
+
+    /**
+     * 上传文件
+     *
+     * @param ossClient  oss连接
+     * @param bucketName 存储空间
+     * @param ossPath    上传文件相对路径+文件名如"upload/2023/01/11/cake.jpg"
+     * @param is         以输入流的形式上传文件
+     * @param fileName   上传文件后新文件名
+     * @return String 返回的唯一MD5数字签名
+     */
+    public static String uploadFileOss(OSS ossClient, String bucketName, String ossPath, InputStream is, String fileName) {
+        try {
+            // 文件大小
+            long fileSize = is.available();
+            // 创建上传Object的Metadata
+            ObjectMetadata metadata = new ObjectMetadata();
+            // 上传的文件的长度
+            metadata.setContentLength(is.available());
+            // 指定该Object被下载时的网页的缓存行为
+            metadata.setCacheControl("no-cache");
+            // 指定该Object下设置Header
+            metadata.setHeader("Pragma", "no-cache");
+            // 指定该Object被下载时的内容编码格式
+            metadata.setContentEncoding("utf-8");
+            // 文件的MIME,定义文件的类型及网页编码,决定浏览器将以什么形式、什么编码读取文件。如果用户没有指定则根据Key或文件名的扩展名生成,
+            // 如果没有扩展名则填默认值application/octet-stream
+            metadata.setContentType(getContentType(fileName));
+            // 指定该Object被下载时的名称(指示MINME用户代理如何显示附加的文件,打开或下载,及文件名称)
+            metadata.setContentDisposition("filename/filesize=" + fileName + "/" + fileSize + "Byte");
+            //上传文件到OSS时需要指定包含文件后缀在内的完整路径如ossPath="upload/2023/01/11/cake.jpg"
+            PutObjectResult putResult = ossClient.putObject(bucketName, ossPath, is, metadata);
+            // 解析结果
+            String resultStr = putResult.getETag();
+            log.info("唯一MD5数字签名:" + resultStr);
+            //上传文件后相对路径如"upload/2023/01/11/cake.jpg"
+            String path = ossPath;
+            return path;
+        } catch (Exception e) {
+            e.printStackTrace();
+            log.error("上传阿里云OSS服务器异常." + e.getMessage(), e);
+            return null;
+        }
+    }
+
+
+    /**
+     * 下载文件到本地
+     *
+     * @param ossClient     oss连接
+     * @param bucketName    存储空间
+     * @param key           Bucket下的文件的路径名+文件名 如:"upload/2023/01/11/cake.jpg"
+     * @param localFilePath 下载本地文件绝对路径如"C:\Users\Administrator\Desktop\oss-download\xxx.pdf"
+     */
+    public static void downloadFileOss(OSS ossClient, String bucketName, String key, String localFilePath) {
+        try {
+            //创建本地文件
+            File file = new File(localFilePath);
+            GetObjectRequest objectRequest = new GetObjectRequest(bucketName, key);
+            //下载OSS文件到本地文件,若指定的本地文件存在则覆盖,否则新建
+            ossClient.getObject(objectRequest, file);
+            log.info("下载文件到本地成功");
+        } catch (OSSException e) {
+            e.printStackTrace();
+        } catch (ClientException e) {
+            e.printStackTrace();
+        }
+    }
+
+
+    /**
+     * 获取上传文件对象
+     * 备注:最重要的是获取上传文件的输出流InputStream
+     *
+     * @param ossClient  oss连接
+     * @param bucketName 存储空间
+     * @param key        Bucket下的文件的路径名+文件名 如:"upload/2023/01/11/cake.jpg"
+     * @return
+     */
+    public static OSSObject getObject(OSS ossClient, String bucketName, String key) {
+        OSSObject object = null;
+        try {
+            object = ossClient.getObject(bucketName, key);
+            //文件大小
+            long fileSize = object.getObjectMetadata().getContentLength();
+            //文件相对路径
+            String ossPath = object.getKey();
+            //文件输入流
+            InputStream is = object.getObjectContent();
+            log.info("success to getObject,fileSize:" + fileSize + "\nossPath:" + ossPath + "\ninputStream:" + is);
+        } catch (OSSException e) {
+            e.printStackTrace();
+        } catch (ClientException e) {
+            e.printStackTrace();
+        }
+        return object;
+    }
+
+
+    /**
+     * 获取上传文件url
+     *
+     * @param ossClient  oss连接
+     * @param bucketName bucketName
+     * @param key        文件全路径
+     * @return
+     */
+    public static String getUrl(OSS ossClient, String bucketName, String key) {
+        //设置URl过期时间为99年:3600L*1000*24*365*99
+        Date expiration = new Date(System.currentTimeMillis() + 3600L * 1000 * 24 * 365 * 99);
+        GeneratePresignedUrlRequest generatePresignedUrlRequest = new GeneratePresignedUrlRequest(bucketName, key);
+        generatePresignedUrlRequest.setExpiration(expiration);
+        URL url = ossClient.generatePresignedUrl(generatePresignedUrlRequest);
+        String returnUrl = url.toString();
+        return returnUrl;
+    }
+
+
+    public static void downloadByFileName(String objectName) {
+        // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。关于其他Region对应的Endpoint信息,请参见访问域名和数据中心。
+//        String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
+        // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
+//        String accessKeyId = "yourAccessKeyId";
+//        String accessKeySecret = "yourAccessKeySecret";
+        // 填写Bucket名称,例如examplebucket。
+//        String bucketName = "examplebucket";
+        // 填写Object完整路径,例如exampledir/exampleobject.txt。Object完整路径中不能包含Bucket名称。
+//        String objectName = "exampledir/exampleobject.txt";
+
+        // 创建OSSClient实例。
+        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
+        try {
+            // ossObject包含文件所在的存储空间名称、文件名称、文件元信息以及一个输入流。
+            OSSObject ossObject = ossClient.getObject(bucketName, objectName);
+            // 读取文件内容。
+            System.out.println("Object content:");
+            BufferedReader reader = new BufferedReader(new InputStreamReader(ossObject.getObjectContent()));
+            while (true) {
+                String line = reader.readLine();
+                if (line == null) {
+                    break;
+                }
+
+                System.out.println("\n" + line);
+            }
+            // 数据读取完成后,获取的流必须关闭,否则会造成连接泄漏,导致请求无连接可用,程序无法正常工作。
+            reader.close();
+            // ossObject对象使用完毕后必须关闭,否则会造成连接泄漏,导致请求无连接可用,程序无法正常工作。
+            ossObject.close();
+
+        } catch (OSSException oe) {
+            System.out.println("Caught an OSSException, which means your request made it to OSS, "
+                    + "but was rejected with an error response for some reason.");
+            System.out.println("Error Message:" + oe.getErrorMessage());
+            System.out.println("Error Code:" + oe.getErrorCode());
+            System.out.println("Request ID:" + oe.getRequestId());
+            System.out.println("Host ID:" + oe.getHostId());
+        } catch (Throwable ce) {
+            System.out.println("Caught an ClientException, which means the client encountered "
+                    + "a serious internal problem while trying to communicate with OSS, "
+                    + "such as not being able to access the network.");
+            System.out.println("Error Message:" + ce.getMessage());
+        } finally {
+            if (ossClient != null) {
+                ossClient.shutdown();
+            }
+        }
+    }
+
+
+    /**
+     * 通过oss的完整key下载
+     *
+     * @param response   response
+     * @param objectName oss完整的key,例子:fj_wechat_web/public/postman.txt
+     */
+    public static void downloadByObjectName(HttpServletResponse response, String objectName) {
+//        String endpointStr = "http://" + endpoint + ".aliyuncs.com";
+        String endpointStr = "http://" + endpoint;
+        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
+        OSSObject ossObject = ossClient.getObject(bucketName, objectName);
+
+        BufferedInputStream in = new BufferedInputStream(ossObject.getObjectContent());
+
+        try {
+            BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
+            //通知浏览器以附件形式下载
+            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("postman.txt", "utf-8"));
+
+            byte[] car = new byte[1024];
+            int len;
+            while ((len = in.read(car)) != -1) {
+                out.write(car, 0, len);
+            }
+            out.flush();
+            out.close();
+            in.close();
+            ossClient.shutdown();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 通过oss的完整key下载
+     *
+     * @param response response
+     * @param url      全路径的url地址 kll/uploads/20230621/07ccbec381a011d121a215719199ac49.html
+     */
+    public static void downloadByUrl(HttpServletResponse response, String url) {
+        downloadByFileName(response, url);
+    }
+
+    /**
+     * @param @param ossFilePath oss上的文件路径(全路径)
+     * @param @param newFilePath 本地文件路径 (全路径)
+     * @return void    返回类型
+     * @Title:downloadToFile
+     * @Description: 下载文件到本地
+     */
+    public static void downloadToFile(String endPoint, String accessKeyId, String accessKeySecret, String bucketName, String ossFilePath, String newFilePath) {
+        //实例化OSSClient对象
+        OSSClient ossClient = (OSSClient) new OSSClientBuilder().build(endPoint, accessKeyId, accessKeySecret);
+        try {
+            // 指定路径如果没有则创建并添加
+            File file = new File(newFilePath);
+            //获取父目录
+            File fileParent = file.getParentFile();
+            //判断是否存在
+            if (!fileParent.exists()) {
+                // 创建父目录文件
+                fileParent.mkdirs();
+            }
+            file.createNewFile();
+            // 下载Object到本地文件,并保存到指定的本地路径中。如果指定的本地文件存在会覆盖,不存在则新建。
+            // 如果未指定本地路径,则下载后的文件默认保存到示例程序所属项目对应本地路径中。
+            ossClient.getObject(new GetObjectRequest(bucketName, ossFilePath), new File(newFilePath));
+
+        } catch (IOException e) {
+            e.printStackTrace();
+        } finally {
+            if (ossClient != null) {
+                ossClient.shutdown();
+            }
+        }
+    }
+
+    /**
+     * 判断文件是否存在
+     *
+     * @param fileName 文件名:postman.txt
+     * @return true文件存在,false文件不存在
+     */
+    public boolean isExitByFileName(String fileName) {
+//        String endpointStr = "http://" + endpoint + ".aliyuncs.com";
+        String endpointStr = "http://" + endpoint;
+        OSS ossClient = new OSSClientBuilder().build(endpointStr, accessKeyId, accessKeySecret);
+        return ossClient.doesObjectExist(bucketName, BASE_DIR + fileName);
+    }
+
+    /**
+     * 判断文件是否存在
+     *
+     * @param url 能直接访问的完整url
+     * @return true文件存在,false文件不存在
+     */
+    public boolean isExitByUrl(String url) {
+        return isExitByFileName(getFileNameByUrl(url));
+    }
+
+    /**
+     * 通过url获取文件名
+     *
+     * @param url 能够直接访问的url
+     * @return 文件名:postman.txt
+     */
+    public static String getFileNameByUrl(String url) {
+        String[] split = url.split("/");
+        return split[split.length - 1];
+    }
+
+    /**
+     * 字符串转成file文件
+     *
+     * @param text
+     * @param file
+     * @return
+     */
+    public static File stringByFile(String text, File file) {
+        if (file.exists()) {
+            file.delete();
+        }
+        BufferedReader br = null;
+        BufferedWriter bw = null;
+        try {
+            br = new BufferedReader(new StringReader(text));
+            bw = new BufferedWriter(new FileWriter(file));
+            //字符缓冲区
+            char[] buf = new char[1024 * 64];
+            int len;
+            while ((len = br.read(buf)) != -1) {
+                bw.write(buf, 0, len);
+            }
+            bw.flush();
+            br.close();
+            bw.close();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return file;
+    }
+
+    /**
+     * file转byte
+     */
+    public static byte[] file2byte(File file) {
+        byte[] buffer = null;
+        try {
+            FileInputStream fis = new FileInputStream(file);
+            ByteArrayOutputStream bos = new ByteArrayOutputStream();
+            byte[] b = new byte[1024];
+            int n;
+            while ((n = fis.read(b)) != -1) {
+                bos.write(b, 0, n);
+            }
+            fis.close();
+            bos.close();
+            buffer = bos.toByteArray();
+        } catch (FileNotFoundException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+        return buffer;
+    }
+
+    /**
+     * byte 转file
+     */
+    public static File byte2File(byte[] buf, String filePath, String fileName) {
+        BufferedOutputStream bos = null;
+        FileOutputStream fos = null;
+        File file = null;
+        try {
+            File dir = new File(filePath);
+            if (!dir.exists() && dir.isDirectory()) {
+                dir.mkdirs();
+            }
+            file = new File(filePath + File.separator + fileName);
+            fos = new FileOutputStream(file);
+            bos = new BufferedOutputStream(fos);
+            bos.write(buf);
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            if (bos != null) {
+                try {
+                    bos.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+            if (fos != null) {
+                try {
+                    fos.close();
+                } catch (IOException e) {
+                    e.printStackTrace();
+                }
+            }
+        }
+        return file;
+    }
+
+    /**
+     * multipartFile转File
+     **/
+    public static File multipartFile2File(MultipartFile multipartFile) {
+        File file = null;
+        if (multipartFile != null) {
+            try {
+                file = File.createTempFile("tmp", null);
+                multipartFile.transferTo(file);
+                System.gc();
+                file.deleteOnExit();
+            } catch (Exception e) {
+                e.printStackTrace();
+                log.warn("multipartFile转File发生异常:" + e);
+            }
+        }
+        return file;
+    }
+
+
+    /**
+     * 删除文件
+     *
+     * @param url 示例:'download/file.xsl' oss服务器文件路径以及文件名
+     *            https://kaiwu-saas.oss-cn-chengdu.aliyuncs.com/kll/uploads/20230621/07ccbec381a011d121a215719199ac49.html
+     *            删除时,去掉默认前缀,只需要相对路径 “kll/uploads/20230621/07ccbec381a011d121a215719199ac49.html”
+     */
+    public static void remove(String url) {
+        try {
+            // 创建OSSClient实例。
+            OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
+            // 判断当前文件url 是否存在
+            boolean exist = ossClient.doesObjectExist(bucketName, url);
+            if (!exist) {
+                System.out.println("文件不存在");
+            } else {
+                // 删除文件。
+                ossClient.deleteObject(bucketName, url);
+                // 关闭OSSClient。
+                ossClient.shutdown();
+
+            }
+        } catch (Exception e) {
+            System.out.println(e);
+        }
+
+    }
+
+
+    /**
+     * 获取OSS连接
+     *
+     * @return
+     */
+    private static void getOSSClient() {
+        if (ossclient == null) {
+            ossclient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
+        }
+    }
+
+    /**
+     * 根据key删除OSS服务器上的文件
+     * <p>
+     * param ossClient oss连接
+     * param bucketName 存储空间
+     * param folder 模拟文件夹名 如"qj_nanjing/"
+     * param key Bucket下的文件的路径名+文件名 如:"upload/cake.jpg"
+     */
+    public static void deleteFile(String bucketName, String folder, String key) {
+        //获取OSS存储client
+        getOSSClient();
+        ossclient.deleteObject(bucketName, folder + key);
+        log.info("删除" + bucketName + "下的文件" + folder + key + "成功");
+    }
+
+    /**
+     * 通过文件名判断并获取OSS服务文件上传时文件的contentType
+     * param fileName 文件名
+     * return 文件的 contentType
+     */
+    public static String getContentTypeByOSS(String fileName) {
+        // 文件的后缀名
+        String fileExtension = fileName.substring(fileName.lastIndexOf("."));
+        if (".bmp".equalsIgnoreCase(fileExtension)) {
+            return "image/bmp";
+        }
+        if (".gif".equalsIgnoreCase(fileExtension)) {
+            return "image/gif";
+        }
+        if (".jpeg".equalsIgnoreCase(fileExtension) || ".jpg".equalsIgnoreCase(fileExtension)
+                || ".png".equalsIgnoreCase(fileExtension)) {
+            return "image/jpeg";
+        }
+        if (".png".equalsIgnoreCase(fileExtension)) {
+            return "image/png";
+        }
+        if (".html".equalsIgnoreCase(fileExtension)) {
+            return "text/html";
+        }
+        if (".txt".equalsIgnoreCase(fileExtension)) {
+            return "text/plain";
+        }
+        if (".vsd".equalsIgnoreCase(fileExtension)) {
+            return "application/vnd.visio";
+        }
+        if (".ppt".equalsIgnoreCase(fileExtension) || "pptx".equalsIgnoreCase(fileExtension)) {
+            return "application/vnd.ms-powerpoint";
+        }
+        if (".doc".equalsIgnoreCase(fileExtension) || "docx".equalsIgnoreCase(fileExtension)) {
+            return "application/msword";
+        }
+        if (".xml".equalsIgnoreCase(fileExtension)) {
+            return "text/xml";
+        }
+        // 默认返回类型
+        return null;
+    }
+
+
+    /**
+     * 下载文件,此处主要是给Controller层提供一个OSS的Object类
+     * objectName示例:download/file.xsl,()这里是oss文件列表中 文件路径和文件名
+     */
+    public static OSSObject downloadOssFile(OutputStream os, String objectName) {
+        // ossObject包含文件所在的存储空间名称、文件名称、文件元信息以及一个输入流。
+        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
+        OSSObject ossObject = ossClient.getObject(bucketName, objectName);
+        return ossObject;
+
+    }
+
+    final static String IMG_FORMAT = "png_jpg_bmp_gif_tif_jpeg_PNG_JPG_BMP_GIF_TIF_JPEG_HEIC_heic";
+    final static String IMG_FORMAT_NUMBER = "8950_ffd8_424d_4749_4d4d_4949_5249";
+
+
+    /**
+     * 针对图片内容的格式效验。
+     * 分别以:
+     * 1:判断后缀名的方式判断是否为图片
+     * 2:以魔术数字进行判断
+     * 3:以imageIO流的方式验证是否为图片
+     *
+     * @param mFile
+     * @return boolean
+     * @author lihao
+     */
+    public static boolean isImage(MultipartFile mFile) {
+        File file = null;
+        InputStream is = null;
+        Image img = null;
+        byte[] bt = new byte[2];
+        try {
+            file = multipartFile2File(mFile);
+            is = new FileInputStream(file);
+            is.read(bt);
+            img = ImageIO.read(file);
+        } catch (IOException e) {
+            return false;
+        }
+
+        //获取文件后缀进行判断
+        String suffix = mFile.getOriginalFilename().substring(mFile.getOriginalFilename().lastIndexOf(".") + 1);
+        if (IMG_FORMAT.indexOf(suffix) == -1) {
+            return false;
+        }
+
+        //以魔术数字进行判断
+        StringBuilder stringBuilder = new StringBuilder();
+        for (int i = 0; i < bt.length; i++) {
+            int v = bt[i] & 0xFF;//byte to int
+            String hv = Integer.toHexString(v);
+            if (hv.length() < 2) {
+                stringBuilder.append(0);
+            }
+            stringBuilder.append(hv);
+        }
+        System.out.println(stringBuilder.toString());
+        if (IMG_FORMAT_NUMBER.indexOf(stringBuilder.toString()) == -1) {
+            return false;
+        }
+
+        //以imageIO流的方式对图片进行格式检查
+        if (img == null || img.getWidth(null) <= 0 || img.getHeight(null) <= 0) {
+            return false;
+        }
+        if (file.exists()) {
+            file.delete();
+        }
+        return true;
+    }
+
+    /**
+     * 给图片添加水印、可设置水印图片旋转角度
+     *
+     * @param logoText 水印文字
+     * @param degree   水印图片旋转角度
+     * @param clarity  透明度(小于1的数)越接近0越透明
+     * @param mFile    被操作的图片
+     */
+    public byte[] waterMarkByText(String logoText,
+                                  Integer degree,
+                                  Float clarity, MultipartFile mFile) {
+        // 图片流
+        InputStream inputStream = null;
+        ByteArrayOutputStream byteStream = null;
+        Image srcImg = null;
+        File file = null;
+        byte[] byteImg = new byte[0];
+
+        //水印添加位置坐标 1像素=1磅*DPI/72 显示屏dpi 大多是72 少数96  这里不对
+        Integer width, height;
+        Integer fontSize = 50;
+        Integer rightButtomOffset = fontSize * 72 / 72 * 6;
+
+        try {
+            file = File.createTempFile("tmp", null);
+            mFile.transferTo(file);
+            srcImg = ImageIO.read(file);
+            width = srcImg.getWidth(null) - rightButtomOffset;
+            height = srcImg.getHeight(null);
+            BufferedImage buffImg = new BufferedImage(srcImg.getWidth(null),
+                    srcImg.getHeight(null), BufferedImage.TYPE_INT_RGB);
+            // 得到画笔对象
+            Graphics2D g = buffImg.createGraphics();
+            // 设置对线段的锯齿状边缘处理
+            g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
+                    RenderingHints.VALUE_INTERPOLATION_BILINEAR);
+            g.drawImage(
+                    srcImg.getScaledInstance(srcImg.getWidth(null),
+                            srcImg.getHeight(null), Image.SCALE_SMOOTH), 0, 0,
+                    null);
+            if (null != degree) {
+                // 设置水印旋转
+                g.rotate(Math.toRadians(degree),
+                        (double) buffImg.getWidth() / 2,
+                        (double) buffImg.getHeight() / 2);
+            }
+            // 设置颜色
+            g.setColor(Color.red);
+            // 设置 Font
+            g.setFont(new Font("宋体", Font.BOLD, fontSize));
+            float alpha = clarity;
+            g.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_ATOP,
+                    alpha));
+            // 第一参数->设置的内容,后面两个参数->文字在图片上的坐标位置(x,y) .
+            g.drawString(logoText, width, height);
+            g.dispose();
+            // 生成图片
+            ImageIO.write(buffImg, "JPG", file);
+            inputStream = new FileInputStream(file);
+            byteStream = new ByteArrayOutputStream();
+            int ch;
+            while ((ch = inputStream.read()) != -1) {
+                byteStream.write(ch);
+            }
+            byteImg = byteStream.toByteArray();
+        } catch (Exception e) {
+            e.printStackTrace();
+        } finally {
+            try {
+                if (null != inputStream) {
+                    inputStream.close();
+                }
+                if (null != byteStream) {
+                    byteStream.close();
+                }
+                if (file.exists()) {
+                    file.delete();
+                }
+            } catch (Exception e) {
+                e.printStackTrace();
+            }
+        }
+        return byteImg;
+    }
+
+    // 测试
+    public static void main(String[] args) throws FileNotFoundException {
+        //阿里云OSS账号自行到阿里云官网申请
+        String ossEndpoint = "XXX";
+        String accessId = "XXX";
+        String accessKey = "XXX";
+        String bucketName = "test";
+        // 初始化OSSClient
+//        OSS ossClient = AliyunOSSClientUtil.getOssClient(ossEndpoint, accessId, accessKey);
+        OSS ossClient = FileUtils.getOssClient(ossEndpoint, accessId, accessKey);
+
+
+        //测试创建多级目录
+        /*String tmpDir = "upload/2023/01/11/";
+        String folder = createFolder(ossClient, bucketName, tmpDir);
+        System.out.println("folder:"+folder);*/
+
+
+        //测试删除文件
+        /*String key="upload/2023/01/11/xxx.pdf";
+        deleteObject(ossClient,bucketName,key);*/
+
+
+        //测试上传文件
+        /*String pathAndname = "C:\\Users\\Administrator\\Desktop\\测试文件上传\\xxx.pdf";
+        File file = new File(pathAndname);
+        //原始文件名:带后缀
+        String oldfilename = file.getName();
+        //新文件名:带后缀
+        String newfilename = "9065df0f3ab72419b36d2dec088e11d6.pdf";//可以自行生成随机唯一文件名
+        String newpath = "C:\\Users\\Administrator\\Desktop\\upload\\2023\\01\\11\\";
+        String ossPath = newpath + newfilename;
+        InputStream is = new FileInputStream(file);
+        String absolutePath = uploadFileOss(ossClient, bucketName, ossPath, is, newfilename);
+        System.out.println("absolutePath:"+absolutePath);*/
+
+
+        //测试获取文件url
+        /*String key="upload/2023/01/11/9065df0f3ab72419b36d2dec088e11d6.pdf";
+        String url = getUrl(ossClient, bucketName, key);
+        System.out.println("url:"+url);*/
+
+
+        //测试获取上传对象
+        /*String key = "upload/2023/01/11/9065df0f3ab72419b36d2dec088e11d6.pdf";
+        getObject(ossClient, bucketName, key);*/
+
+
+        //测试下载文件到本地
+        /*String key = "upload/2023/01/11/9065df0f3ab72419b36d2dec088e11d6.pdf";
+        String localFilePath = "C:\\Users\\Administrator\\Desktop\\oss-download\\xxx.pdf";
+        downloadFileOss(ossClient, bucketName, key, localFilePath);*/
+    }
+
+}

+ 114 - 0
iot-platform-common/src/main/java/com/platform/utils/IdWorker.java

@@ -0,0 +1,114 @@
+package com.platform.utils;
+
+/**
+ * 雪花算法生成ID
+ */
+public class IdWorker {
+    /** 开始时间截 (建议用服务第一次上线的时间,到毫秒级的时间戳) */
+    private final long twepoch = 1651070159429L;
+
+    /** 机器id所占的位数 */
+    private final long workerIdBits = 10L;
+
+    /** 支持的最大机器id,结果是1023 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数) */
+    private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
+
+    /** 序列在id中占的位数 */
+    private final long sequenceBits = 12L;
+
+    /** 机器ID向左移12位 */
+    private final long workerIdShift = sequenceBits;
+
+    /** 时间截向左移22位(10+12) */
+    private final long timestampLeftShift = sequenceBits + workerIdBits;
+
+    /** 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095)
+     * <<为左移,每左移动1位,则扩大1倍
+     * */
+    private final long sequenceMask = -1L ^ (-1L << sequenceBits);
+
+    /** 工作机器ID(0~1024) */
+    private long workerId;
+
+    /** 毫秒内序列(0~4095) */
+    private static long sequence = 0L;
+
+    /** 上次生成ID的时间截 */
+    private static long lastTimestamp = -1L;
+
+    //==============================Constructors=====================================
+    /**
+     * 构造函数
+     * @param workerId 工作ID (0~1023)
+     */
+    public IdWorker(long workerId) {
+        if (workerId > maxWorkerId || workerId < 0) {
+            throw new IllegalArgumentException(String.format("workerId can't be greater than %d or less than 0", maxWorkerId));
+        }
+        this.workerId = workerId;
+    }
+
+    // ==============================Methods==========================================
+    /**
+     * 获得下一个ID (该方法是线程安全的)
+     * @return SnowflakeId
+     */
+    public synchronized long nextId() {
+        long timestamp = timeGen();
+        //如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常
+        if (timestamp < lastTimestamp) {
+            throw new RuntimeException(
+                    String.format("Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
+        }
+
+        //如果是同一时间生成的,则进行毫秒内序列
+        if (lastTimestamp == timestamp) {
+            //如果毫秒相同,则从0递增生成序列号
+            sequence = (sequence + 1) & sequenceMask;
+            //毫秒内序列溢出
+            if (sequence == 0) {
+                //阻塞到下一个毫秒,获得新的时间戳
+                timestamp = tilNextMillis(lastTimestamp);
+            }
+        }
+        //时间戳改变,毫秒内序列重置
+        else {
+            sequence = 0L;
+        }
+
+        //上次生成ID的时间截
+        lastTimestamp = timestamp;
+        //移位并通过或运算拼到一起组成64位的ID
+        long result = ((timestamp - twepoch) << timestampLeftShift)
+                | (workerId << workerIdShift)
+                | sequence;
+        return result;
+    }
+
+    /**
+     * 阻塞到下一个毫秒,直到获得新的时间戳
+     * @param lastTimestamp 上次生成ID的时间截
+     * @return 当前时间戳
+     */
+    protected long tilNextMillis(long lastTimestamp) {
+        long timestamp = timeGen();
+        while (timestamp <= lastTimestamp) {
+            timestamp = timeGen();
+        }
+        return timestamp;
+    }
+
+    /**
+     * 返回以毫秒为单位的当前时间,从1970-01-01 08:00:00算起
+     * @return 当前时间(毫秒)
+     */
+    protected long timeGen() {
+        return System.currentTimeMillis();
+    }
+
+    public static void main(String[] args) {
+        for (int i  = 0; i < 100; i++) {
+            System.out.println(new IdWorker(1).nextId());
+        }
+    }
+}

+ 381 - 0
iot-platform-common/src/main/java/com/platform/utils/PasswordUtils.java

@@ -0,0 +1,381 @@
+package com.platform.utils;
+
+import java.security.MessageDigest;
+
+/**
+ * 密码工具类
+ * @author Louis
+ * @date Sep 1, 2018
+ */
+public class PasswordUtils {
+    public static final int HASH_INTERATIONS = 1024;
+    public static final int SALT_SIZE = 8;
+    public static final int SUB_LENGTH = 16;
+
+    /**
+     * MD5加密
+     * @param inStr 明文
+     * @return 32位密文
+     */
+    public static String md5(String inStr) {
+        MessageDigest md5 = null;
+        try {
+            md5 = MessageDigest.getInstance("MD5");
+            byte[] byteArray = inStr.getBytes("UTF-8");
+            byte[] md5Bytes = md5.digest(byteArray);
+            StringBuffer hexValue = new StringBuffer();
+            for (int i = 0; i < md5Bytes.length; i++) {
+                int val = ((int) md5Bytes[i]) & 0xff;
+                if (val < 16) {
+                    hexValue.append("0");
+                }
+                hexValue.append(Integer.toHexString(val));
+            }
+            return hexValue.toString();
+        } catch (Exception e) {
+            System.out.println(e.toString());
+            e.printStackTrace();
+            return "";
+        }
+    }
+
+    /**
+     * md5密码校验
+     * @param rawPass 明文密码
+     * @param encPass 密文密码
+     * @return
+     */
+    public static boolean matchesMD5(String rawPass, String encPass) {
+        if (md5(rawPass).equals(encPass)) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * 截取密文密码生成盐
+     */
+    public static String generateSalt() {
+        byte[] salt = Digests.generateSalt(SALT_SIZE);
+        return Encodes.encodeHex(salt);
+    }
+
+    /**
+     * 生成安全的密码,生成随机的16位salt并经过1024次 sha-1 hash
+     */
+    public static String entryptPassword(String plainPassword) {
+        byte[] salt = Digests.generateSalt(SALT_SIZE);
+        byte[] hashPassword = Digests.sha1(plainPassword.getBytes(), salt, HASH_INTERATIONS);
+        return Encodes.encodeHex(salt) + Encodes.encodeHex(hashPassword);
+    }
+
+    /**
+     * 生成安全的密码,生成随机的16位salt并经过1024次 sha-1 hash
+     * @param plainPassword 明文密码
+     * @param salt          盐
+     * @return 验证成功返回true
+     */
+    public static String entryptPassword(String plainPassword, String salt) {
+        byte[] saltByte = salt.getBytes();
+        byte[] hashPassword = Digests.sha1(plainPassword.getBytes(), saltByte, HASH_INTERATIONS);
+        return Encodes.encodeHex(saltByte) + Encodes.encodeHex(hashPassword);
+    }
+
+    /**
+     * 验证密码
+     * @param plainPassword 明文密码
+     * @param password      密文密码
+     * @return 验证成功返回true
+     */
+    public static boolean validatePassword(String plainPassword, String password) {
+        byte[] salt = Encodes.decodeHex(password.substring(0, SUB_LENGTH));
+        byte[] hashPassword = Digests.sha1(plainPassword.getBytes(), salt, HASH_INTERATIONS);
+        return password.equals(Encodes.encodeHex(salt) + Encodes.encodeHex(hashPassword));
+    }
+
+    /**
+     * 验证密码
+     * @param plainPassword 明文密码
+     * @param password      密文密码
+     * @param salt          盐
+     * @return 验证成功返回true
+     */
+    public static boolean validatePassword(String plainPassword, String password, String salt) {
+        byte[] saltByte = salt.getBytes();
+        byte[] hashPassword = Digests.sha1(plainPassword.getBytes(), saltByte, HASH_INTERATIONS);
+        return password.equals(Encodes.encodeHex(saltByte) + Encodes.encodeHex(hashPassword));
+    }
+
+    //SELECT CONCAT(id, ',', phone, ',', password, ';,') str from sckw_fleet.kwf_driver ;
+//    public static void checkDriver(){
+//        String str = "162528614993104896,13868885042,fa4d73f8a688b56bc1810a55d6ddfc32fc7b9a01fad3d9750b5b1521;,\n" +
+//                "162528642843283456,18372742349,f9553b1bfa6d9a93a17980bc839541f55c58c52d0c28fb03c5975ac9;,\n" +
+//                "162528661445021696,13682474577,f55d95489b74c0f1f0b695f37567e7497e701f223071808a19c9261c;,\n" +
+//                "162528680059342848,13445521643,1687d32e8effd59b03ea7b5c443815c19ffd71f4a6cc5fd88ac35585;,\n" +
+//                "162528705808175104,18900110011,abbdc7ffa788707ddb73cd71087ecf8bb6171a10a7f7d3d7ed66eff2;,\n" +
+//                "162528792894509056,18726962456,e8d913a0d5a50e67d0c77da4c602cfefb830c1ca4dc00cc7feae7a9e;,\n" +
+//                "162532384737071104,13723972320,47bdadd33eaf853fecc7e4bd75804b85ade5a203250ed4a5bc464c25;,\n" +
+//                "162532402399285248,15791782346,bbecc4516cf0b5572354e4eaca9a615cf724ea9991163adc23319df7;,\n" +
+//                "162532423651823616,17533106183,f64fbd7cf95d04e3f7dd9bf70c7d0fbf9c03188cf1022a83388ac464;,\n" +
+//                "162532442350030848,16665388156,bb3faf4ace4b37d39939ccca1ed655714870798016788db084c04b0a;,\n" +
+//                "162532462239420416,13322117405,94e3ab6d453aea3a4daaf01d18f899b8b7813ddf46419e8ee6004fa0;,\n" +
+//                "162532478853058560,15884485779,cf87a95124d50cec64383da7bee1416c2bffff725f67f14937963618;,\n" +
+//                "162532496150368256,13606526627,f4de5eecf7d05d0162f509d3398984c416516f1865314c0b4147bd7e;,\n" +
+//                "162532512227135488,13152075814,b730ef2e6c132d52aaad78f08ec5f490a8c5c654f2c53ad69f739bc6;,\n" +
+//                "162879320946118656,13778787324,0c53e079d76015688a80f5275cd84b0c869b2bbc5f31f3bf42e28b42;,\n" +
+//                "162885056979800064,13556563372,2a334bd23460376ab205f72bea8db42939d8885ea6487e0655039303;,\n" +
+//                "162894153947025408,16680445687,456a93edc6181221901578faf50e59af6f9322e6453ade1706c5287d;,\n" +
+//                "162899666269114368,15884485773,b5dd5489ea9c62bde7c4b96f89dccc08613a6dcdd9a5041f6bad9d33;,\n" +
+//                "162899741896609792,13447413233,d121c7e7be962f9e385dacfb89cb8a6d34b109e02313ecc0eb0be93a;,\n" +
+//                "163454586206556160,18583328871,4c2d3b238396180e3c4ae5a353e8579ff860eb3feb2178b8c157d886;,\n" +
+//                "163965635959721984,18583328873,c900ba7b6a0a5270d51a612d6b3b3d7c1182035a31e16db6fcd509b4;,\n" +
+//                "166974007806005248,19500000099,5dcaf43a00b3ed7c1c51fd32bce313d60d06d561dca033aa75cdd06b;,\n" +
+//                "166979180402053120,19500000069,b84a34ecab63b787809e1df9d87e4d2fc9363b79f1608203331a65c7;,\n" +
+//                "166979180473356288,19500000070,a9a997a9f97d04da8bccd6f2fd63c2e46933c4f484e60e5ee0e53287;,\n" +
+//                "166979180548853760,19500000071,4c1721423a226e2d339a8ca817a173e75ebfbf7feda3c5482bd2545a;,\n" +
+//                "166979180620156928,19500000072,8c8ee4d0c16bb9cc2574b99b34295cd215fa19166270ac77036774ad;,\n" +
+//                "166979180695654400,19500000073,89e971ddb05ddf753d0b4c8dc8f8ae467fdc48ba7616befb9eee43b3;,\n" +
+//                "166979180762763264,19500000074,c8c035a374d62d7ec760db261fa7348519d111161cc5de923d90e54a;,\n" +
+//                "166979180838260736,19500000075,381073889a0e6d16cbb958fe6db49d8b56f71b9ae79640776ec46aaa;,\n" +
+//                "166979180896980992,19500000076,ce83efb5b22d3ebf999baf08077ad0e30597824baf70533e1149954a;,\n" +
+//                "166979180989255680,19500000077,3020906e4e9c0a2fac6fc9b299326ef97e307d2e6df53a4dcd0330e7;,\n" +
+//                "166979181056364544,19500000078,9a7d43c3c506d6be42b68ccaee512bcebfa6ad9bde5840bc84bc59db;,\n" +
+//                "166979181110890496,19500000079,bc618cba847d2c023930c41707d0409470f81b78ae0236873462e3a8;,\n" +
+//                "166979181169610752,19500000080,19dc91f8b87ee075b9df6eb589176e59dae7ceb6623770a85b54038e;,\n" +
+//                "166979181236719616,19500000081,abd3d8506775b5fb0dd3e3595d9e31bf250fa23d82b7a6b289c7ba61;,\n" +
+//                "166979181295439872,19500000082,e5fb3886bfa37342b4f3792e183c6cf5a276601ea2fe11fdee89af1a;,\n" +
+//                "166979181404491776,19500000083,6dbc2a8c788d1e6bea6a8cfa2585eb4d907d92f153f3d94697b64109;,\n" +
+//                "166979181475794944,19500000084,5029b1475afa8ce6d7c1a60b80475d9b5dee180c70de1c74029a7726;,\n" +
+//                "166979181538709504,19500000085,215f5d15fd7951f0351e570150467ebf8ca89639491f61745c22cc7d;,\n" +
+//                "166979181589041152,19500000086,9f4b4456afabb0f147361fb9631104ac1ab955396a59f2fab89f5015;,\n" +
+//                "166979181643567104,19500000087,5c007ab468137c636097a72efa0dbb731db44bef5ff87425dc23d5d8;,\n" +
+//                "166979181698093056,19500000088,94c9d496b91681870c36a6c69e0e595f7cd2caa7608f45342a0b1a4f;,\n" +
+//                "166979181752619008,19500000089,3f37860a1435c494ebe9e2e9e3c8ae3ace669a36058cac2ef4c126f0;,\n" +
+//                "166979181807144960,19500000090,7e507b6a549f8e7de9759b91cf13784d3f9192eedc57543194eb1bc6;,\n" +
+//                "166979182029443072,19500000091,8012fc3b3310d763b2e431b2cb728842b189fa2694a36c39b34803ad;,\n" +
+//                "166979182092357632,19500000092,57a41f35b66543f6b2744d7ab8bb4d6874dc786ad53830a3080b9c2d;,\n" +
+//                "166979182184632320,19500000093,289285ea9961fa8262f2700885c26e9487b8ae3b89ba6ea72a63a130;,\n" +
+//                "166979182243352576,19500000094,1f4226de4d2df148e9dd5a17bf67c433ce8d7f5cec43465bae96e9c2;,\n" +
+//                "166979182293684224,19500000095,0490dc000e6dd21530bffcce3f2e02f4de6406e65eccb0b9157c4d8d;,\n" +
+//                "166979182352404480,19500000096,97d7d20af5a9c6becc697a0d667b6275ca21cdfc3de6f290c513b160;,\n" +
+//                "166979182406930432,19500000097,017ffd866343fb28f3e315b72b6e13d098a6168f2de22379f5993949;,\n" +
+//                "166979182465650688,19500000098,51ad2c225b6940f98d62e0945f7479db3b464e0266d0877e0e21cfb7;,\n" +
+//                "167213991624445952,19500000055,b47056210b158ca57b35907206bda7afaf1d4b6eb70922563feb3b34;,\n" +
+//                "167213991754469376,19500000056,4cf5663948054ab50f0b4eb8d66e82c9b14777e06a48b4ac56f342ef;,\n" +
+//                "167213991813189632,19500000057,6a364842ed98d03fc78ae61111794171791e7c2017de54d67c374297;,\n" +
+//                "167213991909658624,19500000058,81c6cdefd625468af303339db329190ad46996fe0ff6686de6c86e7a;,\n" +
+//                "167213991964184576,19500000059,21a0f70bf87e6a3c8d6e4e49b84d1a7819957207682933654056b72c;,\n" +
+//                "167213992027099136,19500000060,88404bed55005f80e1a61d22969a2effe7955606fe7289d64b3ade5f;,\n" +
+//                "167213992090013696,19500000061,c674846dcd0d3bacc69e488d8ba477af75a76f533932c0a3e95491b6;,\n" +
+//                "167213992144539648,19500000062,66b84316146a56c56f8b5706a4601278f235490c8fc2e6fd1dc27cc7;,\n" +
+//                "167213992207454208,19500000063,e28acaa45401be9162305d3b1e83fb372b8f0da139ffc054585c920c;,\n" +
+//                "167213992274563072,19500000064,86a679de0ab614cc0afdc3d22688ff832f05c6fbc1057d4630d2b52c;,\n" +
+//                "167213992329089024,19500000065,61bb806f0a125f0fc3e21ee73db9e53caa7dd51e3d63064eb1966e34;,\n" +
+//                "167213992400392192,19500000066,07fc1f3f7354d9335d8c0937a4839c16a7a672ec11787131979bfc62;,\n" +
+//                "167213992459112448,19500000067,b8e9a1aa729fa4ab9aa771d1a844b1e06cf023adec4185ab17f7b79e;,\n" +
+//                "167213992551387136,19500000068,68b1afac745118d6a67bbea775acc5e1756856cd450897f9097706f1;,\n" +
+//                "170549931663167488,17358629955,8364df818959f2c4a27607bced79945e09973a32121d96bd5c4710a9;,\n" +
+//                "172375269049372672,18581845668,3f57140083d2558bdfcb8a319b52b3c86f992af5dde4b21007ea5733;,\n" +
+//                "172442643224072192,19500000001,3e742de4560ce2ed6658119124f26b097a5c0d19b577b95c6aaca509;,\n" +
+//                "172442643400232960,19500000002,3d6020290d2d8f05e34884e1cff29e99be8a299c4dc4af4008f7d39f;,\n" +
+//                "172442643479924736,19500000003,077fe8b72511e26077e2c7bcc2bc9ad98e905dd10dfaf4b50c1d72fb;,\n" +
+//                "173041758513401856,19988888888,7080f75c426af4a958092ea7d40fc3c8d4c7ddb4fa9d847153788368;,\n" +
+//                "173043956366446592,15902849627,be354600d28ea42df3df93aeb6cb08a33674effe54f46e5394bf491c;,\n" +
+//                "177401688267689984,15515950395,0bdbc09d1c08e53286dfe3d2dcd3c014341055d65744331d81a1e3b8;,\n" +
+//                "184341399146074112,19600000090,aebcacc7e710a97fa381aaf8426de9826d6a0985f555ccf4669d4960;,\n" +
+//                "184341699865088000,19600000091,af779edd56faf31dd9a92c24e82a834045a3126cc0b09b52d3409827;,\n" +
+//                "184342227026186240,19600000092,bedd46ac733d0b64fe599541b463b16ac3cf68a79cfb6e04ee31e962;,\n" +
+//                "185002976673271808,15515955555,d5ce819e1cf9988686cb8665368ead4a08841f0a90e40ecf9eb683d6;,\n" +
+//                "185003553801113600,18283808586,50e1e1389468deb93322ea3c091878b2586dc486fe917cf9097ab3c4;,\n" +
+//                "192321823566729216,16612341231,d13779d353a8c3db5656bb395a27303b4aefda8ec135a4f8265e0616;,\n" +
+//                "192321823675781120,16612341232,eaf94160cb3ccdebe9bbe98df17751fbcf3d1e7f07d71a1b19b2626e;,\n" +
+//                "192321823822581760,16612341233,739b5b9fa279879a5a5e17917960164cd2a573721fe7ffdb188852d1;,\n" +
+//                "192321823906467840,16612341234,175b2cba6cd4d713a6ab08b1c32f8e76c87027a6812469689540da5c;,\n" +
+//                "192321823981965312,16612341235,5d745fda9bf8d5f86863d658751ef8a7c86cbc8184733cbfa1e8dc4f;,\n" +
+//                "192321824061657088,16612341236,b25748c67ab38eabf06c9d6f2c2c3f867ecac3c1a26cf4332d68d42a;,\n" +
+//                "192321824149737472,16612341237,d142b7439d2e75e7d2c5b9aac2255b4de80bf71374b2181b7b50f9aa;,\n" +
+//                "192321824246206464,16612341238,2f06cc01f3185ae6237d82f310c0d7952c67b2395660f7be3d9b1ac6;,\n" +
+//                "192321824317509632,16612341239,2d8d693e43d2460fae648f361bfd66d0ee2735af3bced6b2b9b1bd5d;,\n" +
+//                "192321824397201408,16612341240,95791a4a26edb107cb0f3f7801136e07f7075b8be8d0be2da88549eb";
+//        String [] strArray = str.split(";,");
+//
+//        for (int i=0; i<strArray.length; i++) {
+//            String str1 = strArray[i];
+//            if (StringUtils.isBlank(str1.trim())) {
+//                continue;
+//            }
+//            String [] strArray1 = str1.split(",");
+//            String id = strArray1[0];
+//            String account = strArray1[1];
+//            String password = strArray1[2];
+//            System.out.print("-- " + account + "==>");
+//
+//            String md5 = PasswordUtils.md5(account);
+//            boolean bool = PasswordUtils.validatePassword(md5, password);
+//
+//            if (!bool) {
+//                md5 = PasswordUtils.md5("123456");
+//                bool = PasswordUtils.validatePassword(md5, password);
+//                if (bool) {
+//                    System.out.println(bool);
+//                    String salt = PasswordUtils.generateSalt();
+//                    md5 = PasswordUtils.md5("123456");
+//                    password = PasswordUtils.entryptPassword(account + md5, salt);
+//                    String sql = "UPDATE sckw_fleet.kwf_driver set password = '"+password+"', salt = '"+salt+"' where id = "+id+";";
+//                    System.out.println(sql);
+//                } else {
+//                    System.out.println(bool);
+//                    String salt = PasswordUtils.generateSalt();
+//                    md5 = PasswordUtils.md5(account);
+//                    password = PasswordUtils.entryptPassword(account + md5, salt);
+//                    String sql = "UPDATE sckw_fleet.kwf_driver set password = '"+password+"', salt = '"+salt+"' where id = "+id+";";
+//                    System.out.println(sql);
+//                }
+//            } else {
+//                System.out.println(bool);
+//                String salt = PasswordUtils.generateSalt();
+//                md5 = PasswordUtils.md5(account);
+//                password = PasswordUtils.entryptPassword(account + md5, salt);
+//                String sql = "UPDATE sckw_fleet.kwf_driver set password = '"+password+"', salt = '"+salt+"' where id = "+id+";";
+//                System.out.println(sql);
+//            }
+//        }
+//    }
+
+    //SELECT CONCAT(id, ',', account, ',', password, ';,')  str from sckw_system.kws_user ;
+//    public static void checkUser(){
+//        String str = "156382319433748480,18000000000,be8d1ae3fac3067ee98068cce2895ad305febbe31a644fe42954de0c;,\n" +
+//                "156383116720607232,admin,04323ed6811d048e0406ec39293394aabcf9b132a0cb1b87dc78279f;,\n" +
+//                "162301006506364928,182838089858,cf2f6d38f0b8a150d90d9194b97875c004413880cf7aba8abf3b3dc7;,\n" +
+//                "162604062133456896,13000000000,cf2f6d38f0b8a150d90d9194b97875c004413880cf7aba8abf3b3dc7;,\n" +
+//                "163980531141185536,18283808586,debc2bab5eaf7b629049666051ad504bc60bea9eeab95932f64054a9;,\n" +
+//                "163987895701475328,15902849627,ecc16d89238b2cd77637b41096e322a3f89c345ac10297a5fc7b61e3;,\n" +
+//                "163994695842664448,18283808587,0a842bee1f75c4939d408eae02f575fad005cec391b7cc1eec6f5882;,\n" +
+//                "163995870587523072,18283808581,1b7383f4d6e458fb610bcc7a80cc959ed13c83a30063401b82fa1245;,\n" +
+//                "163995977299005440,18283808582,cebab3009b34e77708385c2af5595de5e739aadf435542d22d1b66ec;,\n" +
+//                "163996113957818368,18827222222,3182b6bba4c90445e2d16a8901653866a707d9a1a2dc499f8af37546;,\n" +
+//                "163996259454029824,18827766520,4b32a9a0b4dabe5b920a78d5115febf3b87d45ceebe5715d11b53dad;,\n" +
+//                "163996369839722496,17722337872,c676f2924969a10ce4f059b1894bded8061a01d0252f3a789ce8b9ad;,\n" +
+//                "163998264054517760,13911111111,65ffa259c8ba2660438f28a09851182b615dc16b7188006d67d2d661;,\n" +
+//                "164072870236917760,18591918877,9ca66c47aad850e4b22b7df5acbe58a33b3a1be4fa70315e9eff8bf2;,\n" +
+//                "164357889975128064,18283808584,1fd478d1d3f61d341c6cc1065b9e02833e314102be2528fbf292ed87;,\n" +
+//                "164480042405990400,18283765365,ce181135763e284d6748012dbe53bcac767ea60d0306b0f04e1b3ffd;,\n" +
+//                "164697036837359616,18583328873,cf2f6d38f0b8a150d90d9194b97875c004413880cf7aba8abf3b3dc7;,\n" +
+//                "164697518171492352,333,9bb4f1afbdf520c28a8a9f9e4a568a4743ad62f319a17ed9437414b5;,\n" +
+//                "169411694739591168,18725603264,5ea1c34a749cfd9c84b9aad577c5bae2cf12444a1f4b6c2bbac6cf67;,\n" +
+//                "169832563756503040,18989898989,796c6a422bce78cced07918f759fe9ed5ee300ea3953e00fc71c24cc;,\n" +
+//                "169832563794250001,17358629900,15896f181b1311a52fea135b46d95dceb14a9be0a9f70e5471fdbed8;,\n" +
+//                "169832563794250002,18581845600,1b26b8eeba0c5dfc6ec66bea3d5a744e1f254db639114e290f328a36;,\n" +
+//                "172804004273721344,17358629955,1b26b8eeba0c5dfc6ec66bea3d5a744e1f254db639114e290f328a36;,\n" +
+//                "172804804509175808,18581845668,5c14b84bf8b4ff37289367942d176ae99353d4554cd68504d480099f;,\n" +
+//                "172805173922500608,19940686355,f90c137bf2dafdbd0f44c737f3308dd3b6eccc9ca901f8561655235f;,\n" +
+//                "174848836286550016,18728803519,ffe135b89706c8118e183f6e2724605be2e57eaef88a83fa161988b7;,\n" +
+//                "174849409274613760,18728803520,5a70e23e8f39c898151c2f220c0b4b8cc5ec325754871e05cc97ad6f;,\n" +
+//                "174921932133634048,18508243826,154e6e02db2c56eb30e012053ad6f1e3aa1c3124057f6fd1ff08c1b1;,\n" +
+//                "175194057557938176,18583328875,c1048c9ae5cbb7c3479611eb279780ee2f4bf4e14e518fb416e04889;,\n" +
+//                "177044507026526208,17780832879,2ce6f28d73a8741b4f9621bb533fc7a041341438afcf9240fa06e694;,\n" +
+//                "177154391646670848,18728803521,fb776988fb19dd63086ae88f37de4a01fdce26038bbba073b33e5533;,\n" +
+//                "177493080700620800,17358629911,ffcc7ac864f6d951318db5643078bacf95499c2c9f0b376e30d31134;,\n" +
+//                "177493191988088832,17358629922,5ee3b6ee0049014f63ae1288b9f731c8ae05e674169245539ef9d8cf;,\n" +
+//                "177493399400615936,17358629901,e8a9cdf5659204ce9b16cade7073764c0a3b2136bd1750b563132190;,\n" +
+//                "177493603818409984,17358629933,d6bd668a876e4dcdc9eefb6059a4e9c2969d8ce54b3d42f5b9a49573;,\n" +
+//                "177495184064385024,18581845611,53f2cb77f34992dc1785d662792df69d1f7e52e50450a87446b31445;,\n" +
+//                "177495269858873344,18581845622,9e397e5e54145865a9a3c55d75ea4c5105847daf6937eb0b9d66ee9e;,\n" +
+//                "177495384933797888,18581845633,bc425341f50b1f2b26f1f4092d212147022912e96c022c6b8e85e2b0;,\n" +
+//                "177496454816862208,19940686311,31c8cc61c09d079e26ed7dbaf7b650a36addbacab8e094c7744b4f4f;,\n" +
+//                "177496522529705984,19940686322,7ff53f4b835ca96d36a0683d7d3ea6e597d47e11005948b113962b22;,\n" +
+//                "177496618457632768,19940686333,cf7fce7ad2d0912cc8b655c71b7984a4f679184ab6f0121b34b2cddf;,\n" +
+//                "177755619585953792,18581845644,492a18b9c21963e38bd5c5be7aea349f9fbba6256bc5409e882ed165;,\n" +
+//                "177756009534590976,19940686344,8f53c645f492e0856baf623bdd1d9ba94715397de929223e17f3b311;,\n" +
+//                "177756500125552640,17358629944,b046904d8cff8812692a078307d233bf18a6ed12751dc6e540f1d17c;,\n" +
+//                "179251265040027648,18900001111,17b95c44a4be220ec241ea66fac83941afbd438fe97b9aba4e587f19;,\n" +
+//                "179251480232988672,18900002222,7a98d8432666fbae4f976be6aee0725d83fc85e9a4140400ac3fc08b;,\n" +
+//                "179287301304619008,15770000850,457b71ac5eb35cd72f54f260dc2e720f435ad18e3fec50c5f308f16e;,\n" +
+//                "179567500780900352,18215677925,1212403ea6c37724ce3deccf3a3e84c82cd5503cac054782329e0b38;,\n" +
+//                "179908046275743744,17310362742,e68281cfa1b49d333e51e9773fb955e10908795987892282e004791e;,\n" +
+//                "180714251143352320,5464,4e834fbf535588ab64752d3609e3606eae0387cbfdc1a011626f0af1;,\n" +
+//                "180716172793090048,1534543545,2df806f9dad1fe9aa1afb3592ff309e3c6821fe9f593ffcc7c765d4f;,\n" +
+//                "180717765986881536,34234,514134b6e51a189d5e02d1e439d6616aedbe5e73395970efe01fffc5;,\n" +
+//                "180741718713307136,16500000000,61d1ece89fac8414762ab7faa173cf8707c7e7137cd22e93652ccb4a;,\n" +
+//                "180742245102653440,16600000000,2e7a7e603c4883cc5bd859af38482d4fab1eec756a7653cad697becd;,\n" +
+//                "182077378799865856,15515955555,5957560d39adc6269948ae1a2eda73c1a451164557a831e025fdc0d9;,\n" +
+//                "182445986600194048,14000000000,475211e9bdb02f694c17a468ba33f395c87cdcda6ef343a2c7dc86a2;,\n" +
+//                "182446432941248512,17000000000,ca0feeb8ca30dae8ab38d2ff07840f731777d6514c92cd5dfdc1902d;,\n" +
+//                "184622287863943168,17358621111,f4e4bab7497534fdf1487ce2951fbaf0d8b9463f6ad7166275dc9a84;,\n" +
+//                "184622549060030464,17358622222,424df61b9291ada971db0005c29be190602165aeb2c9295c107ce8b9;,\n" +
+//                "187262271745953792,18777777777,27005458fed283da910fcbcfea4cc877454ab47164525074fc6792a1;,\n" +
+//                "187263867661848576,18900000000,b41bc19f522840bcf88da64d8fc93d9938252856c95d174d24796796;,\n" +
+//                "187266156040556544,18666666666,b83ca58b0f533a98bbb9a72857725aca1ceb8476ac6a6118fb5ea7cf;,\n" +
+//                "187266875430801408,18555555555,256f34d839db85a12eb46c21135a9d0b9a058ba26e83099b3951275f;,\n" +
+//                "187674506012135424,14777777777,dd4a6928d63b57f85a5dad13b5f6581ddaef2f47ce613f6d8cebed15;,\n" +
+//                "187932221632417792,18922111111,915d03daa67403dace1077063afff2f99bc78f27cf1eff476267637d;,\n" +
+//                "187933261320687616,18922111112,d10029a3a9f3176ee2ea6516add9f94e0273cd5e1e507eca5e9c8754;,\n" +
+//                "191139325050621952,18912349988,b36e322666a0b260d5b5bbcba6622f30ce59653892044830f9988554;,\n" +
+//                "191958030668009472,18922993333,bbf608392522d9c2faf7015c376e1a762ac7108ac9cb089d9ca4baf8;,\n" +
+//                "191973351617466368,16666666666,94e66bf955c8ec094bf202350438ffffcc2c203141d9b98f4c47f671;,\n" +
+//                "192247281867558912,16600060066,9aec2a414a09c87257ac8d0b5d53b6828c255a51a57a271c54266e56;,\n" +
+//                "192337955283537920,17777777777,028515cdef747a5eea5a268c30906af1661e08a8807bf2f702b8ca66;,\n" +
+//                "193055960644718592,14444444444,0fbacd064a22b0e35152991552a11cb793ded61438d713912667c5ec";
+//        String [] strArray = str.split(";,");
+//
+//        for (int i=0; i<strArray.length; i++) {
+//            String str1 = strArray[i];
+//            if (StringUtils.isBlank(str1.trim())) {
+//                continue;
+//            }
+//            String [] strArray1 = str1.split(",");
+//            String id = strArray1[0];
+//            String account = strArray1[1];
+//            String password = strArray1[2];
+//            System.out.print("-- " + account + "==>");
+//
+//            String md5 = PasswordUtils.md5(account);
+//            boolean bool = PasswordUtils.validatePassword(md5, password);
+//
+//            if (!bool) {
+//                md5 = PasswordUtils.md5("123456");
+//                bool = PasswordUtils.validatePassword(md5, password);
+//                if (bool) {
+//                    System.out.println(bool);
+//                    String salt = PasswordUtils.generateSalt();
+//                    md5 = PasswordUtils.md5("123456");
+//                    password = PasswordUtils.entryptPassword(account + md5, salt);
+//                    String sql = "UPDATE sckw_system.kws_user set password = '"+password+"', salt = '"+salt+"' where id = "+id+";";
+//                    System.out.println(sql);
+//                } else {
+//                    System.out.println(bool);
+//                    String salt = PasswordUtils.generateSalt();
+//                    md5 = PasswordUtils.md5(account);
+//                    password = PasswordUtils.entryptPassword(account + md5, salt);
+//                    String sql = "UPDATE sckw_system.kws_user set password = '"+password+"', salt = '"+salt+"' where id = "+id+";";
+//                    System.out.println(sql);
+//                }
+//            } else {
+//                System.out.println(bool);
+//                String salt = PasswordUtils.generateSalt();
+//                md5 = PasswordUtils.md5(account);
+//                password = PasswordUtils.entryptPassword(account + md5, salt);
+//                String sql = "UPDATE sckw_system.kws_user set password = '"+password+"', salt = '"+salt+"' where id = "+id+";";
+//                System.out.println(sql);
+//            }
+//        }
+//    }
+
+    public static void main(String[] args) throws Exception {
+        String account = "admin";
+        String password = "123456";
+        String salt = generateSalt();
+        System.out.println(salt);
+
+        String md5 = PasswordUtils.md5(password);
+        System.out.println(md5);
+        String password1 = PasswordUtils.entryptPassword(account + md5, salt);
+        System.out.println(password1);
+
+        boolean bool = PasswordUtils.validatePassword(account + md5, password1, salt);
+        System.out.println(bool);
+        //checkDriver();
+        //checkUser();
+    }
+}

+ 39 - 0
iot-platform-manager/src/main/java/com/platform/api/controller/WeighbridgeController.java

@@ -0,0 +1,39 @@
+package com.platform.api.controller;
+
+import com.platform.api.request.WeighbridgePushRequest;
+import com.platform.exception.BaseResult;
+import com.platform.manage.WeighbridgeRecordManage;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.*;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.math.BigDecimal;
+
+/**
+ * 地磅数据上报接口
+ * @author cxf
+ */
+@Tag(name = "地磅数据接口", description = "地磅过磅数据上报相关接口")
+@RestController
+@RequestMapping("/api/v1/device")
+@RequiredArgsConstructor
+@Slf4j
+public class WeighbridgeController {
+
+    private final WeighbridgeRecordManage weighbridgeRecordManage;
+
+    /**
+     * 地磅过磅数据上报
+     */
+    @Operation(summary = "地磅过磅数据上报", description = "接收地磅设备上报的过磅数据和图片")
+    @PostMapping("/weighBridgePush")
+    public BaseResult<Boolean> weighBridgePush(WeighbridgePushRequest request) {
+        // 构建请求对象
+        // 调用业务层处理;
+        return BaseResult.success(weighbridgeRecordManage.handleWeighbridgePush(request));
+    }
+}

+ 58 - 0
iot-platform-manager/src/main/java/com/platform/api/request/WeighbridgePushRequest.java

@@ -0,0 +1,58 @@
+package com.platform.api.request;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.math.BigDecimal;
+
+/**
+ * 地磅过磅数据上报请求参数
+ * @author PC
+ */
+@Data
+@Schema(description = "地磅过磅数据上报请求参数")
+public class WeighbridgePushRequest {
+
+    /**
+     * 车牌号
+     */
+    @NotBlank(message = "车牌号不能为空")
+    @Schema(description = "车牌号", example = "川A1234")
+    private String licensePlate;
+
+    /**
+     * 地磅编号
+     */
+    @NotBlank(message = "地磅编号不能为空")
+    @Schema(description = "地磅编号", example = "10100111")
+    private String weighbridgeCode;
+
+    /**
+     * 称重重量(吨)
+     */
+    @NotNull(message = "称重重量不能为空")
+    @Schema(description = "称重重量(吨)", example = "34.5")
+    private BigDecimal grossWeight;
+
+    /**
+     * 时间戳(支持秒或毫秒)
+     */
+    @NotNull(message = "时间戳不能为空")
+    @Schema(description = "时间戳(秒或毫秒)", example = "1745483981")
+    private Long timestamp;
+
+    /**
+     * 处理标签,用于指定处理方向
+     */
+    @Schema(description = "处理标签", example = "kll")
+    private String tag;
+
+    /**
+     * 车辆图片
+     */
+    @Schema(description = "车辆图片数组")
+    private MultipartFile[] images;
+}

+ 1 - 1
iot-platform-manager/src/main/java/com/platform/entity/WeighbridgeRecord.java

@@ -9,7 +9,7 @@ import java.time.LocalDateTime;
 /**
  * 地磅过磅记录表实体类
  *
- * @author Auto Generated
+ * @author cxf
  */
 @Data
 @TableName("weighbridge_records")

+ 124 - 0
iot-platform-manager/src/main/java/com/platform/manage/WeighbridgeRecordManage.java

@@ -0,0 +1,124 @@
+package com.platform.manage;
+
+import com.platform.api.request.WeighbridgePushRequest;
+import com.platform.entity.WeighbridgeRecord;
+import com.platform.enums.ErrorCodeEnum;
+import com.platform.exception.IotException;
+import com.platform.service.WeighbridgeRecordService;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.util.Arrays;
+import java.util.stream.Collectors;
+
+/**
+ * 地磅记录业务编排类
+ * @author PC
+ */
+@Service
+@RequiredArgsConstructor
+@Slf4j
+public class WeighbridgeRecordManage {
+
+    private final WeighbridgeRecordService weighbridgeRecordService;
+
+    /**
+     * 处理地磅过磅数据上报
+     * @param request 地磅上报请求参数
+     * @return 是否保存成功
+     */
+    public Boolean handleWeighbridgePush(WeighbridgePushRequest request) {
+        log.info("处理地磅数据上报 - 车牌:{}, 地磅编号:{}, 重量:{}, 时间戳:{}", 
+                request.getLicensePlate(), 
+                request.getWeighbridgeCode(), 
+                request.getGrossWeight(), 
+                request.getTimestamp());
+
+        try {
+            // 构建实体对象
+            WeighbridgeRecord record = buildWeighbridgeRecord(request);
+
+            // 保存到数据库
+            boolean saved = weighbridgeRecordService.save(record);
+            
+            if (saved) {
+                log.info("地磅数据保存成功 - ID: {}, 车牌: {}", record.getId(), record.getLicensePlate());
+                return true;
+            } else {
+                log.error("地磅数据保存失败 - 车牌: {}", request.getLicensePlate());
+                throw new IotException(ErrorCodeEnum.DATA_SAVE_FAIL, "地磅数据保存失败");
+            }
+
+        } catch (IotException e) {
+            throw e;
+        } catch (Exception e) {
+            log.error("地磅数据上报处理异常", e);
+            throw new IotException(ErrorCodeEnum.SYSTEM_ERROR, "地磅数据上报异常: " + e.getMessage());
+        }
+    }
+
+    /**
+     * 构建地磅记录实体对象
+     * @param request 请求参数
+     * @return 地磅记录实体
+     */
+    private WeighbridgeRecord buildWeighbridgeRecord(WeighbridgePushRequest request) {
+        WeighbridgeRecord record = new WeighbridgeRecord();
+        
+        // 基础信息
+        record.setLicensePlate(request.getLicensePlate());
+        record.setWeighbridgeCode(request.getWeighbridgeCode());
+        record.setWeight(request.getGrossWeight());
+        record.setTag(request.getTag());
+
+        // 时间戳转换:自动识别秒/毫秒
+        LocalDateTime weighTime = convertTimestamp(request.getTimestamp());
+        record.setWeighTime(weighTime);
+
+        // 处理图片文件名(仅保存文件名,逗号分隔)
+        if (request.getImages() != null && request.getImages().length > 0) {
+            String photoUrls = processImageFiles(request.getImages());
+            record.setPhotoUrls(photoUrls);
+            log.info("处理图片文件 - 数量: {}, 文件名: {}", request.getImages().length, photoUrls);
+        }
+
+        return record;
+    }
+
+    /**
+     * 处理图片文件,提取文件名并拼接
+     * @param images 图片文件数组
+     * @return 逗号分隔的文件名字符串
+     */
+    private String processImageFiles(MultipartFile[] images) {
+        return Arrays.stream(images)
+                .map(MultipartFile::getOriginalFilename)
+                .filter(name -> name != null && !name.isEmpty())
+                .collect(Collectors.joining(","));
+    }
+
+    /**
+     * 时间戳转换:自动识别秒/毫秒
+     * @param timestamp 时间戳(秒或毫秒)
+     * @return LocalDateTime
+     */
+    private LocalDateTime convertTimestamp(Long timestamp) {
+        // 判断是秒还是毫秒(10位为秒,13位为毫秒)
+        String timestampStr = timestamp.toString();
+        if (timestampStr.length() == 10) {
+            // 秒级时间戳
+            return LocalDateTime.ofInstant(Instant.ofEpochSecond(timestamp), ZoneId.systemDefault());
+        } else if (timestampStr.length() == 13) {
+            // 毫秒级时间戳
+            return LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), ZoneId.systemDefault());
+        } else {
+            log.error("时间戳格式错误,长度: {}, 值: {}", timestampStr.length(), timestamp);
+            throw new IotException(ErrorCodeEnum.PARAM_ERROR, "时间戳格式错误,仅支持10位秒级或13位毫秒级时间戳");
+        }
+    }
+}

+ 1 - 1
iot-platform-manager/src/main/java/com/platform/mapper/WeighbridgeRecordMapper.java

@@ -5,7 +5,7 @@ import com.platform.entity.WeighbridgeRecord;
 import org.apache.ibatis.annotations.Mapper;
 
 /**
- * @Author: Auto Generated
+ * @Author: cxf
  * @CreateTime: 2026-01-21
  * @Description: 地磅过磅记录Mapper接口
  * @Version: 1.0

+ 1 - 1
iot-platform-manager/src/main/java/com/platform/service/WeighbridgeRecordService.java

@@ -4,7 +4,7 @@ import com.baomidou.mybatisplus.extension.service.IService;
 import com.platform.entity.WeighbridgeRecord;
 
 /**
- * @Author: Auto Generated
+ * @Author: cxf
  * @CreateTime: 2026-01-21
  * @Description: 地磅过磅记录Service接口
  * @Version: 1.0

+ 1 - 1
iot-platform-manager/src/main/java/com/platform/service/impl/WeighbridgeRecordServiceImpl.java

@@ -7,7 +7,7 @@ import com.platform.service.WeighbridgeRecordService;
 import org.springframework.stereotype.Service;
 
 /**
- * @Author: Auto Generated
+ * @Author: cxf
  * @CreateTime: 2026-01-21
  * @Description: 地磅过磅记录Service实现类
  * @Version: 1.0

+ 18 - 0
pom.xml

@@ -45,6 +45,8 @@
         <knife4j.version>4.5.0</knife4j.version>
 		<maven-compiler-plugin.version>3.14.0</maven-compiler-plugin.version>
 		<lombok.version>1.18.38</lombok.version>
+		<oss.version>2.2.0.RELEASE</oss.version>
+		<hutool.version>5.8.18</hutool.version>
 	</properties>
 	<dependencyManagement>
 		<dependencies>
@@ -128,6 +130,22 @@
 				<artifactId>spring-cloud-starter-openfeign</artifactId>
 				<version>4.1.1</version> <!-- 与Spring Cloud 2023.0.1匹配 -->
 			</dependency>
+			<dependency>
+				<groupId>com.alibaba.cloud</groupId>
+				<artifactId>spring-cloud-starter-alicloud-oss</artifactId>
+				<version>${oss.version}</version>
+			</dependency>
+			<!--hutool-->
+			<dependency>
+				<groupId>cn.hutool</groupId>
+				<artifactId>hutool-http</artifactId>
+				<version>${hutool.version}</version>
+			</dependency>
+			<dependency>
+				<groupId>cn.hutool</groupId>
+				<artifactId>hutool-extra</artifactId>
+				<version>${hutool.version}</version>
+			</dependency>
 		</dependencies>
 	</dependencyManagement>
 	<build>